1
+ <script setup>
2
+ import { ref , computed } from " vue" ;
3
+ import LocalVueUiFunnel from ' ../src/components/vue-ui-funnel.vue' ;
4
+ import LocalVueDataUi from ' ../src/components/vue-data-ui.vue' ;
5
+ import Box from " ./Box.vue" ;
6
+ import convertArrayToObject from " ./convertModel" ;
7
+ import { useArena } from " ../src/useArena"
8
+
9
+ const { local , build , vduiLocal , vduiBuild , toggleTable } = useArena ()
10
+
11
+ const dataset = ref ([
12
+ {
13
+ name: ' Lead' ,
14
+ value: 7745.8234576
15
+ },
16
+ {
17
+ name: ' Opportunity' ,
18
+ value: 5468
19
+ },
20
+ {
21
+ name: ' Qualified' ,
22
+ value: 4238
23
+ },
24
+ {
25
+ name: ' Sold' ,
26
+ value: 2025
27
+ },
28
+ {
29
+ name: ' Retained' ,
30
+ value: 1520
31
+ },
32
+ ])
33
+
34
+ const model = ref ([
35
+ { key: ' responsive' , def: false , type: ' checkbox' },
36
+ { key: ' useCssAnimation' , def: true , type: ' checkbox' },
37
+ { key: ' style.chart.backgroundColor' , def: ' #FFFFFF' , type: ' color' },
38
+ { key: ' style.chart.color' , def: ' #1A1A1A' , type: ' color' },
39
+ { key: ' style.chart.width' , def: 600 , type: ' range' , min: 300 , max: 1000 },
40
+ { key: ' style.chart.height' , def: 500 , type: ' range' , min: 300 , max: 1000 },
41
+
42
+ { key: ' style.chart.title.text' , def: ' Title' , type: ' text' , label: ' textContent' , category: ' title' },
43
+ { key: ' style.chart.title.color' , def: ' #1A1A1A' , type: ' color' , label: ' textColor' , category: ' title' },
44
+ { key: ' style.chart.title.fontSize' , def: 20 , type: ' number' , min: 6 , max: 48 , label: ' fontSize' , category: ' title' },
45
+ { key: ' style.chart.title.bold' , def: true , type: ' checkbox' , label: ' bold' , category: ' title' },
46
+ { key: ' style.chart.title.textAlign' , def: ' center' , type: ' select' , options: [' left' , ' center' , ' right' ]},
47
+ { key: ' style.chart.title.paddingLeft' , def: 0 , type: ' number' , min: 0 , max: 24 },
48
+ { key: ' style.chart.title.paddingRight' , def: 0 , type: ' number' , min: 0 , max: 24 },
49
+
50
+ { key: ' style.chart.title.subtitle.text' , def: ' Lorem ipsum dolor sit amet' , type: ' text' , label: ' textContent' , category: ' subtitle' },
51
+ { key: ' style.chart.title.subtitle.color' , def: ' #A1A1A1' , type: ' color' , label: ' textColor' , category: ' subtitle' },
52
+ { key: ' style.chart.title.subtitle.fontSize' , def: 16 , type: ' number' , min: 6 , max: 42 , label: ' fontSize' , category: ' subtitle' },
53
+ { key: ' style.chart.title.subtitle.bold' , def: false , type: ' checkbox' , label: ' bold' , category: ' subtitle' },
54
+
55
+ { key: ' style.chart.padding.top' , def: 12 , type: ' number' , min: 0 , max: 200 },
56
+ { key: ' style.chart.padding.right' , def: 128 , type: ' number' , min: 0 , max: 200 },
57
+ { key: ' style.chart.padding.bottom' , def: 24 , type: ' number' , min: 0 , max: 200 },
58
+ { key: ' style.chart.padding.left' , def: 24 , type: ' number' , min: 0 , max: 200 },
59
+
60
+ { key: ' style.chart.barCircleSpacingRatio' , def: 0.05 , type: ' range' , min: 0 , max: 0.5 , step: 0.01 },
61
+
62
+ { key: ' style.chart.circles.stroke' , def: ' #FFFFFF' , type: ' color' },
63
+ { key: ' style.chart.circles.strokeWidth' , def: 1 , type: ' range' , min: 0 , max: 12 },
64
+ { key: ' style.chart.circles.dataLabels.fontSize' , def: 16 , min: 8 , max: 48 , type: ' range' },
65
+ { key: ' style.chart.circles.dataLabels.offsetY' , def: 0 , min: - 100 , max: 100 , type: ' number' },
66
+ { key: ' style.chart.circles.dataLabels.adaptColorToBackground' , def: true , type: ' checkbox' },
67
+ { key: ' style.chart.circles.dataLabels.color' , def: ' #1A1A1A' , type: ' color' },
68
+ { key: ' style.chart.circles.dataLabels.rounding' , def: 1 , type: ' number' , min: 0 , max: 6 },
69
+ { key: ' style.chart.circles.dataLabels.bold' , def: true , type: ' checkbox' },
70
+
71
+ { key: ' style.chart.circleLinks.show' , def: true , type: ' checkbox' },
72
+ { key: ' style.chart.circleLinks.color' , def: ' #E1E5E8' , type: ' color' },
73
+ { key: ' style.chart.circleLinks.widthRatio' , def: 1 , type: ' range' , min: 0.1 , max: 2 , step: 0.01 },
74
+
75
+ { key: ' style.chart.area.show' , def: true , type: ' checkbox' },
76
+ { key: ' style.chart.area.color' , def: ' #e1e5e8' , type: ' color' },
77
+
78
+ { key: ' style.chart.bars.stroke' , def: ' #FFFFFF' , type: ' color' },
79
+ { key: ' style.chart.bars.defaultColor' , def: ' #1f77b4' , type: ' color' },
80
+ { key: ' style.chart.bars.strokeWidth' , def: 1 , type: ' range' , min: 0 , max: 12 },
81
+ { key: ' style.chart.bars.gapRatio' , def: 0.2 , type: ' range' , min: 0 , max: 1 , step: 0.01 },
82
+ { key: ' style.chart.bars.borderRadius' , def: 3 , min: 0 , max: 24 , type: ' range' },
83
+
84
+ { key: ' style.chart.bars.dataLabels.name.fontSize' , def: 16 , type: ' number' , min: 8 , max: 42 },
85
+ { key: ' style.chart.bars.dataLabels.name.color' , def: ' #1A1A1A' , type: ' color' },
86
+ { key: ' style.chart.bars.dataLabels.name.bold' , def: true , type: ' checkbox' },
87
+ { key: ' style.chart.bars.dataLabels.name.offsetX' , def: 0 , type: ' number' , min: - 100 , max: 100 },
88
+ { key: ' style.chart.bars.dataLabels.name.offsetY' , def: 0 , type: ' number' , min: - 100 , max: 100 },
89
+
90
+ { key: ' style.chart.bars.dataLabels.value.fontSize' , def: 16 , type: ' number' , min: 8 , max: 42 },
91
+ { key: ' style.chart.bars.dataLabels.value.rounding' , def: 0 , type: ' number' , min: 0 , max: 6 },
92
+ { key: ' style.chart.bars.dataLabels.value.bold' , def: false , type: ' checkbox' },
93
+ { key: ' style.chart.bars.dataLabels.value.color' , def: ' #1A1A1A' , type: ' color' },
94
+ { key: ' style.chart.bars.dataLabels.value.prefix' , def: ' P' , type: ' text' },
95
+ { key: ' style.chart.bars.dataLabels.value.suffix' , def: ' S' , type: ' text' },
96
+ { key: ' style.chart.bars.dataLabels.value.offsetX' , def: 0 , type: ' number' , min: - 100 , max: 100 },
97
+ { key: ' style.chart.bars.dataLabels.value.offsetY' , def: 0 , type: ' number' , min: - 100 , max: 100 },
98
+ ])
99
+
100
+ const themeOptions = ref ([
101
+ " " ,
102
+ " hack" ,
103
+ " zen" ,
104
+ " concrete" ,
105
+ " default"
106
+ ])
107
+
108
+ const currentTheme = ref (themeOptions .value [4 ])
109
+
110
+ const config = computed (() => {
111
+ const c = convertArrayToObject (model .value );
112
+
113
+ return {
114
+ theme: currentTheme .value ,
115
+ ... c,
116
+ style: {
117
+ ... c .style ,
118
+ chart: {
119
+ ... c .style .chart ,
120
+ circles: {
121
+ ... c .style .chart .circles ,
122
+ dataLabels: {
123
+ ... c .style .chart .circles .dataLabels ,
124
+ // formatter: ({ value, config }) => {
125
+ // console.log(config)
126
+ // return `CIR ${value}`
127
+ // }
128
+ }
129
+ },
130
+ bars: {
131
+ ... c .style .chart .bars ,
132
+ dataLabels: {
133
+ ... c .style .chart .bars .dataLabels ,
134
+ value: {
135
+ ... c .style .chart .bars .dataLabels .value ,
136
+ // formatter: ({ value, config }) => {
137
+ // console.log(config)
138
+ // return `BAR ${value}`
139
+ // }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ })
147
+
148
+ const step = ref (0 );
149
+
150
+ </script >
151
+
152
+ <template >
153
+ <div style =" margin : 12px 0 ; color : white " >
154
+ Theme:
155
+ <select v-model =" currentTheme" @change =" step += 1" >
156
+ <option v-for =" opt in themeOptions" >{{ opt }}</option >
157
+ </select >
158
+ </div >
159
+
160
+ <div style =" width : 600px ; height : 600px ; resize : both ; overflow : auto ; background : white " >
161
+ <LocalVueUiFunnel :key =" `responsive_${step}`" :dataset =" dataset" :config =" {
162
+ ...config,
163
+ responsive: true
164
+ }" >
165
+ </LocalVueUiFunnel >
166
+ </div >
167
+
168
+ <Box >
169
+ <template #title >VueUiFunnel</template >
170
+
171
+ <template #local >
172
+ <LocalVueUiFunnel :dataset =" dataset" :config =" config" >
173
+ <template #source >
174
+ #source
175
+ </template >
176
+ <template #watermark =" { isPrinting } " >
177
+ <div v-if =" isPrinting" style =" font-size : 100px ; opacity : 0.1 ; transform : rotate (-10deg )" >
178
+ WATERMARK
179
+ </div >
180
+ </template >
181
+ <template #optionPdf >
182
+ PRINT PDF
183
+ </template >
184
+ <template #svg =" { svg } " >
185
+ <g style =" pointer-events : none ;" >
186
+ <circle :cx =" svg.width - 30" :cy =" svg.height / 2" :r =" 30" fill =" #42d392" />
187
+ <text :x =" svg.width - 30" :y =" svg.height / 2" text-anchor =" middle" >#SVG</text >
188
+ </g >
189
+ </template >
190
+ </LocalVueUiFunnel >
191
+ </template >
192
+
193
+ <template #VDUI-local >
194
+ <LocalVueDataUi component =" VueUiFunnel" :dataset =" dataset" :config =" config" >
195
+ <template #source >
196
+ #source
197
+ </template >
198
+ <template #watermark =" { isPrinting } " >
199
+ <div v-if =" isPrinting" style =" font-size : 100px ; opacity : 0.1 ; transform : rotate (-10deg )" >
200
+ WATERMARK
201
+ </div >
202
+ </template >
203
+ <template #optionPdf >
204
+ PRINT PDF
205
+ </template >
206
+ <template #svg =" { svg } " >
207
+ <g style =" pointer-events : none ;" >
208
+ <circle :cx =" svg.width - 30" :cy =" svg.height / 2" :r =" 30" fill =" #42d392" />
209
+ <text :x =" svg.width - 30" :y =" svg.height / 2" text-anchor =" middle" >#SVG</text >
210
+ </g >
211
+ </template >
212
+ </LocalVueDataUi >
213
+ </template >
214
+
215
+ <template #build >
216
+ <VueUiFunnel :dataset =" dataset" :config =" config" >
217
+ <template #source >
218
+ #source
219
+ </template >
220
+ <template #watermark =" { isPrinting } " >
221
+ <div v-if =" isPrinting" style =" font-size : 100px ; opacity : 0.1 ; transform : rotate (-10deg )" >
222
+ WATERMARK
223
+ </div >
224
+ </template >
225
+ <template #optionPdf >
226
+ PRINT PDF
227
+ </template >
228
+ <template #svg =" { svg } " >
229
+ <g style =" pointer-events : none ;" >
230
+ <circle :cx =" svg.width - 30" :cy =" svg.height / 2" :r =" 30" fill =" #42d392" />
231
+ <text :x =" svg.width - 30" :y =" svg.height / 2" text-anchor =" middle" >#SVG</text >
232
+ </g >
233
+ </template >
234
+ </VueUiFunnel >
235
+ </template >
236
+
237
+ <template #VDUI-build >
238
+ <VueDataUi component =" VueUiFunnel" :dataset =" dataset" :config =" config" >
239
+ <template #source >
240
+ #source
241
+ </template >
242
+ <template #watermark =" { isPrinting } " >
243
+ <div v-if =" isPrinting" style =" font-size : 100px ; opacity : 0.1 ; transform : rotate (-10deg )" >
244
+ WATERMARK
245
+ </div >
246
+ </template >
247
+ <template #optionPdf >
248
+ PRINT PDF
249
+ </template >
250
+ <template #svg =" { svg } " >
251
+ <g style =" pointer-events : none ;" >
252
+ <circle :cx =" svg.width - 30" :cy =" svg.height / 2" :r =" 30" fill =" #42d392" />
253
+ <text :x =" svg.width - 30" :y =" svg.height / 2" text-anchor =" middle" >#SVG</text >
254
+ </g >
255
+ </template >
256
+ </VueDataUi >
257
+ </template >
258
+
259
+ <template #knobs >
260
+ <div
261
+ style =" display : flex ; flex-direction : row ; flex-wrap :wrap ; align-items :center ; width : 100% ; color : #CCCCCC ; gap :24px ;" >
262
+ <div v-for =" knob in model" >
263
+ <label style =" font-size : 10px " >{{ knob.key }}</label >
264
+ <div
265
+ style =" display :flex ; flex-direction :row ; flex-wrap : wrap ; align-items :center ; gap :6px ; height : 40px " >
266
+ <input v-if =" !['none', 'select'].includes(knob.type)" :step =" knob.step" :type =" knob.type"
267
+ :min =" knob.min ?? 0" :max =" knob.max ?? 0" v-model =" knob.def" @change =" step += 1" >
268
+ <select v-if =" knob.type === 'select'" v-model =" knob.def" @change =" step += 1" >
269
+ <option v-for =" opt in knob.options" >{{ opt }}</option >
270
+ </select >
271
+ </div >
272
+ </div >
273
+ </div >
274
+ </template >
275
+ </Box >
276
+ </template >
0 commit comments