create-foldkit-app 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/base/FOLDKIT.md +3 -1
- package/dist/templates/examples/canvas-art/src/main.ts +1 -1
- package/dist/templates/examples/charting/src/chartHost.ts +3 -4
- package/dist/templates/examples/charting/src/entry.ts +0 -2
- package/dist/templates/examples/charting/src/view/chart.ts +101 -36
- package/dist/templates/examples/embedding/src/main.ts +3 -3
- package/dist/templates/examples/generative-art/src/subscription.ts +1 -1
- package/dist/templates/examples/job-application/src/step/education/education.ts +14 -16
- package/dist/templates/examples/job-application/src/step/skills/skills.ts +14 -16
- package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +14 -16
- package/dist/templates/examples/map/src/entry.ts +1 -2
- package/dist/templates/examples/map/src/main.ts +123 -145
- package/dist/templates/examples/map/src/mapHost.ts +10 -12
- package/dist/templates/examples/map/src/mount.test.ts +93 -68
- package/dist/templates/examples/pixel-art/src/subscription.ts +5 -5
- package/dist/templates/examples/routing/src/main.ts +3 -3
- package/dist/templates/examples/slow-warnings/src/main.ts +4 -4
- package/dist/templates/examples/snake/src/main.ts +4 -3
- package/dist/templates/examples/ssg/src/entry.server.ts +2 -0
- package/dist/templates/examples/ssg/src/entry.ts +1 -0
- package/dist/templates/examples/ssr/package.json +1 -1
- package/dist/templates/examples/ssr/src/entry.server.ts +2 -0
- package/dist/templates/examples/ssr/src/entry.ts +1 -0
- package/dist/templates/examples/stopwatch/src/main.ts +1 -0
- package/dist/templates/examples/ui-showcase/src/main.ts +49 -37
- package/dist/templates/examples/ui-showcase/src/ui/subscriptions.ts +1 -18
- package/dist/templates/examples/ui-showcase/src/ui/update.ts +2 -12
- package/dist/templates/examples/ui-showcase/src/ui/view/calendar.ts +9 -7
- package/dist/templates/examples/ui-showcase/src/ui/view/checkbox.ts +80 -65
- package/dist/templates/examples/ui-showcase/src/ui/view/dialog.ts +102 -123
- package/dist/templates/examples/ui-showcase/src/ui/view/disclosure.ts +128 -120
- package/dist/templates/examples/ui-showcase/src/ui/view/fieldset.ts +173 -144
- package/dist/templates/examples/ui-showcase/src/ui/view/fileDrop.ts +17 -15
- package/dist/templates/examples/ui-showcase/src/ui/view/hoverIntent.ts +64 -56
- package/dist/templates/examples/ui-showcase/src/ui/view/input.ts +32 -33
- package/dist/templates/examples/ui-showcase/src/ui/view/meter.ts +82 -73
- package/dist/templates/examples/ui-showcase/src/ui/view/popover.ts +100 -81
- package/dist/templates/examples/ui-showcase/src/ui/view/progress.ts +83 -68
- package/dist/templates/examples/ui-showcase/src/ui/view/radioGroup.ts +79 -85
- package/dist/templates/examples/ui-showcase/src/ui/view/select.ts +63 -67
- package/dist/templates/examples/ui-showcase/src/ui/view/slider.ts +72 -72
- package/dist/templates/examples/ui-showcase/src/ui/view/switch.ts +25 -26
- package/dist/templates/examples/ui-showcase/src/ui/view/tabs.ts +58 -46
- package/dist/templates/examples/ui-showcase/src/ui/view/textarea.ts +32 -39
- package/dist/templates/examples/ui-showcase/src/ui/view/tooltip.ts +48 -36
- package/dist/templates/examples/websocket-chat/src/main.ts +44 -18
- package/dist/templates/examples/websocket-chat/src/story.test.ts +33 -6
- package/dist/templates/release.json +12 -11
- package/dist/templates/rendering/ssg/src/entry.server.ts +2 -0
- package/dist/templates/rendering/ssg/src/entry.ts +1 -0
- package/dist/templates/rendering/ssg/vite.config.ts +1 -0
- package/dist/templates/rendering/ssr/scripts/serve.ts +4 -145
- package/dist/templates/rendering/ssr/src/entry.server.ts +2 -0
- package/dist/templates/rendering/ssr/src/entry.ts +1 -0
- package/dist/templates/rendering/ssr/vite.config.ts +1 -0
- package/dist/utils/files.js +2 -0
- package/package.json +1 -1
- package/dist/templates/examples/charting/src/subscription.ts +0 -70
|
@@ -59,6 +59,83 @@ const checkPlaceholder = (h: HtmlBuilder<UiMessage>): Html => {
|
|
|
59
59
|
|
|
60
60
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
61
61
|
(model, h): Html => {
|
|
62
|
+
const verticalPlanOptionsView = ({
|
|
63
|
+
group,
|
|
64
|
+
options,
|
|
65
|
+
}: RadioGroup.RenderInfo<Plan>): Html =>
|
|
66
|
+
h.div(
|
|
67
|
+
[...group, h.Class(verticalGroupClassName)],
|
|
68
|
+
options.map(option => {
|
|
69
|
+
const plan = option.value
|
|
70
|
+
return h.div(
|
|
71
|
+
[...option.option, h.Class(verticalOptionClassName)],
|
|
72
|
+
[
|
|
73
|
+
h.div(
|
|
74
|
+
[h.Class('flex w-full items-center justify-between')],
|
|
75
|
+
[
|
|
76
|
+
h.div(
|
|
77
|
+
[],
|
|
78
|
+
[
|
|
79
|
+
h.span(
|
|
80
|
+
[...option.label, h.Class(labelClassName)],
|
|
81
|
+
[plan],
|
|
82
|
+
),
|
|
83
|
+
h.p(
|
|
84
|
+
[...option.description, h.Class(descriptionClassName)],
|
|
85
|
+
[planDescriptions[plan]],
|
|
86
|
+
),
|
|
87
|
+
],
|
|
88
|
+
),
|
|
89
|
+
h.div(
|
|
90
|
+
[h.Class('flex items-center gap-3')],
|
|
91
|
+
[
|
|
92
|
+
h.span([h.Class(priceClassName)], [planPrices[plan]]),
|
|
93
|
+
option.isSelected ? checkIcon(h) : checkPlaceholder(h),
|
|
94
|
+
],
|
|
95
|
+
),
|
|
96
|
+
],
|
|
97
|
+
),
|
|
98
|
+
],
|
|
99
|
+
)
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
const horizontalPlanOptionsView = ({
|
|
104
|
+
group,
|
|
105
|
+
options,
|
|
106
|
+
}: RadioGroup.RenderInfo<Plan>): Html =>
|
|
107
|
+
h.div(
|
|
108
|
+
[...group, h.Class(horizontalGroupClassName)],
|
|
109
|
+
options.map(option => {
|
|
110
|
+
const plan = option.value
|
|
111
|
+
return h.div(
|
|
112
|
+
[...option.option, h.Class(horizontalOptionClassName)],
|
|
113
|
+
[
|
|
114
|
+
h.div(
|
|
115
|
+
[h.Class('flex w-full items-center justify-between')],
|
|
116
|
+
[
|
|
117
|
+
h.div(
|
|
118
|
+
[],
|
|
119
|
+
[
|
|
120
|
+
h.span(
|
|
121
|
+
[...option.label, h.Class(labelClassName)],
|
|
122
|
+
[plan],
|
|
123
|
+
),
|
|
124
|
+
h.p(
|
|
125
|
+
[...option.description, h.Class(descriptionClassName)],
|
|
126
|
+
[planDescriptions[plan]],
|
|
127
|
+
),
|
|
128
|
+
],
|
|
129
|
+
),
|
|
130
|
+
option.isSelected ? checkIcon(h) : checkPlaceholder(h),
|
|
131
|
+
],
|
|
132
|
+
),
|
|
133
|
+
h.span([h.Class(priceClassName + ' mt-2')], [planPrices[plan]]),
|
|
134
|
+
],
|
|
135
|
+
)
|
|
136
|
+
}),
|
|
137
|
+
)
|
|
138
|
+
|
|
62
139
|
return h.div(
|
|
63
140
|
[],
|
|
64
141
|
[
|
|
@@ -80,51 +157,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
80
157
|
options: plans,
|
|
81
158
|
ariaLabel: 'Server plan',
|
|
82
159
|
hasOptionDescription: () => true,
|
|
83
|
-
toView:
|
|
84
|
-
h.div(
|
|
85
|
-
[...group, h.Class(verticalGroupClassName)],
|
|
86
|
-
options.map(option => {
|
|
87
|
-
const plan = option.value
|
|
88
|
-
return h.div(
|
|
89
|
-
[...option.option, h.Class(verticalOptionClassName)],
|
|
90
|
-
[
|
|
91
|
-
h.div(
|
|
92
|
-
[h.Class('flex w-full items-center justify-between')],
|
|
93
|
-
[
|
|
94
|
-
h.div(
|
|
95
|
-
[],
|
|
96
|
-
[
|
|
97
|
-
h.span(
|
|
98
|
-
[...option.label, h.Class(labelClassName)],
|
|
99
|
-
[plan],
|
|
100
|
-
),
|
|
101
|
-
h.p(
|
|
102
|
-
[
|
|
103
|
-
...option.description,
|
|
104
|
-
h.Class(descriptionClassName),
|
|
105
|
-
],
|
|
106
|
-
[planDescriptions[plan]],
|
|
107
|
-
),
|
|
108
|
-
],
|
|
109
|
-
),
|
|
110
|
-
h.div(
|
|
111
|
-
[h.Class('flex items-center gap-3')],
|
|
112
|
-
[
|
|
113
|
-
h.span(
|
|
114
|
-
[h.Class(priceClassName)],
|
|
115
|
-
[planPrices[plan]],
|
|
116
|
-
),
|
|
117
|
-
option.isSelected
|
|
118
|
-
? checkIcon(h)
|
|
119
|
-
: checkPlaceholder(h),
|
|
120
|
-
],
|
|
121
|
-
),
|
|
122
|
-
],
|
|
123
|
-
),
|
|
124
|
-
],
|
|
125
|
-
)
|
|
126
|
-
}),
|
|
127
|
-
),
|
|
160
|
+
toView: verticalPlanOptionsView,
|
|
128
161
|
},
|
|
129
162
|
toParentMessage: message =>
|
|
130
163
|
UiMessage.GotVerticalRadioGroupDemoMessage({ message }),
|
|
@@ -144,46 +177,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
144
177
|
ariaLabel: 'Server plan',
|
|
145
178
|
orientation: 'Horizontal',
|
|
146
179
|
hasOptionDescription: () => true,
|
|
147
|
-
toView:
|
|
148
|
-
h.div(
|
|
149
|
-
[...group, h.Class(horizontalGroupClassName)],
|
|
150
|
-
options.map(option => {
|
|
151
|
-
const plan = option.value
|
|
152
|
-
return h.div(
|
|
153
|
-
[...option.option, h.Class(horizontalOptionClassName)],
|
|
154
|
-
[
|
|
155
|
-
h.div(
|
|
156
|
-
[h.Class('flex w-full items-center justify-between')],
|
|
157
|
-
[
|
|
158
|
-
h.div(
|
|
159
|
-
[],
|
|
160
|
-
[
|
|
161
|
-
h.span(
|
|
162
|
-
[...option.label, h.Class(labelClassName)],
|
|
163
|
-
[plan],
|
|
164
|
-
),
|
|
165
|
-
h.p(
|
|
166
|
-
[
|
|
167
|
-
...option.description,
|
|
168
|
-
h.Class(descriptionClassName),
|
|
169
|
-
],
|
|
170
|
-
[planDescriptions[plan]],
|
|
171
|
-
),
|
|
172
|
-
],
|
|
173
|
-
),
|
|
174
|
-
option.isSelected
|
|
175
|
-
? checkIcon(h)
|
|
176
|
-
: checkPlaceholder(h),
|
|
177
|
-
],
|
|
178
|
-
),
|
|
179
|
-
h.span(
|
|
180
|
-
[h.Class(priceClassName + ' mt-2')],
|
|
181
|
-
[planPrices[plan]],
|
|
182
|
-
),
|
|
183
|
-
],
|
|
184
|
-
)
|
|
185
|
-
}),
|
|
186
|
-
),
|
|
180
|
+
toView: horizontalPlanOptionsView,
|
|
187
181
|
},
|
|
188
182
|
toParentMessage: message =>
|
|
189
183
|
UiMessage.GotHorizontalRadioGroupDemoMessage({ message }),
|
|
@@ -21,6 +21,67 @@ const descriptionClassName = 'text-sm text-gray-500'
|
|
|
21
21
|
|
|
22
22
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
23
23
|
(model, h): Html => {
|
|
24
|
+
const countryOptions = (): ReadonlyArray<Html> => [
|
|
25
|
+
h.option([h.Value('us')], ['United States']),
|
|
26
|
+
h.option([h.Value('ca')], ['Canada']),
|
|
27
|
+
h.option([h.Value('gb')], ['United Kingdom']),
|
|
28
|
+
h.option([h.Value('au')], ['Australia']),
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
const basicSelectView = (
|
|
32
|
+
attributes: Select.SelectAttributes<UiMessage>,
|
|
33
|
+
): Html =>
|
|
34
|
+
h.div(
|
|
35
|
+
[h.Class('flex flex-col gap-1.5 w-full')],
|
|
36
|
+
[
|
|
37
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Country']),
|
|
38
|
+
h.div(
|
|
39
|
+
[h.Class(selectWrapperClassName)],
|
|
40
|
+
[
|
|
41
|
+
h.select(
|
|
42
|
+
[...attributes.select, h.Class(selectClassName)],
|
|
43
|
+
countryOptions(),
|
|
44
|
+
),
|
|
45
|
+
h.span(
|
|
46
|
+
[h.Class(chevronClassName)],
|
|
47
|
+
[Icon.chevronDown('w-4 h-4')],
|
|
48
|
+
),
|
|
49
|
+
],
|
|
50
|
+
),
|
|
51
|
+
h.span(
|
|
52
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
53
|
+
['Where you currently reside.'],
|
|
54
|
+
),
|
|
55
|
+
],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
const disabledSelectView = (
|
|
59
|
+
attributes: Select.SelectAttributes<UiMessage>,
|
|
60
|
+
): Html =>
|
|
61
|
+
h.div(
|
|
62
|
+
[h.Class('flex flex-col gap-1.5 max-w-sm')],
|
|
63
|
+
[
|
|
64
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Country']),
|
|
65
|
+
h.div(
|
|
66
|
+
[h.Class(selectWrapperClassName)],
|
|
67
|
+
[
|
|
68
|
+
h.select(
|
|
69
|
+
[...attributes.select, h.Class(selectClassName)],
|
|
70
|
+
countryOptions(),
|
|
71
|
+
),
|
|
72
|
+
h.span(
|
|
73
|
+
[h.Class(chevronClassName)],
|
|
74
|
+
[Icon.chevronDown('w-4 h-4')],
|
|
75
|
+
),
|
|
76
|
+
],
|
|
77
|
+
),
|
|
78
|
+
h.span(
|
|
79
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
80
|
+
['This select is disabled.'],
|
|
81
|
+
),
|
|
82
|
+
],
|
|
83
|
+
)
|
|
84
|
+
|
|
24
85
|
return h.div(
|
|
25
86
|
[],
|
|
26
87
|
[
|
|
@@ -39,41 +100,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
39
100
|
value: model.selectDemoValue,
|
|
40
101
|
hasDescription: true,
|
|
41
102
|
onChange: value => UiMessage.UpdatedSelectDemoValue({ value }),
|
|
42
|
-
toView:
|
|
43
|
-
h.div(
|
|
44
|
-
[h.Class('flex flex-col gap-1.5 w-full')],
|
|
45
|
-
[
|
|
46
|
-
h.label(
|
|
47
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
48
|
-
['Country'],
|
|
49
|
-
),
|
|
50
|
-
h.div(
|
|
51
|
-
[h.Class(selectWrapperClassName)],
|
|
52
|
-
[
|
|
53
|
-
h.select(
|
|
54
|
-
[...attributes.select, h.Class(selectClassName)],
|
|
55
|
-
[
|
|
56
|
-
h.option([h.Value('us')], ['United States']),
|
|
57
|
-
h.option([h.Value('ca')], ['Canada']),
|
|
58
|
-
h.option([h.Value('gb')], ['United Kingdom']),
|
|
59
|
-
h.option([h.Value('au')], ['Australia']),
|
|
60
|
-
],
|
|
61
|
-
),
|
|
62
|
-
h.span(
|
|
63
|
-
[h.Class(chevronClassName)],
|
|
64
|
-
[Icon.chevronDown('w-4 h-4')],
|
|
65
|
-
),
|
|
66
|
-
],
|
|
67
|
-
),
|
|
68
|
-
h.span(
|
|
69
|
-
[
|
|
70
|
-
...attributes.description,
|
|
71
|
-
h.Class(descriptionClassName),
|
|
72
|
-
],
|
|
73
|
-
['Where you currently reside.'],
|
|
74
|
-
),
|
|
75
|
-
],
|
|
76
|
-
),
|
|
103
|
+
toView: basicSelectView,
|
|
77
104
|
},
|
|
78
105
|
h,
|
|
79
106
|
),
|
|
@@ -90,38 +117,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
90
117
|
isDisabled: true,
|
|
91
118
|
hasDescription: true,
|
|
92
119
|
value: 'us',
|
|
93
|
-
toView:
|
|
94
|
-
h.div(
|
|
95
|
-
[h.Class('flex flex-col gap-1.5 max-w-sm')],
|
|
96
|
-
[
|
|
97
|
-
h.label(
|
|
98
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
99
|
-
['Country'],
|
|
100
|
-
),
|
|
101
|
-
h.div(
|
|
102
|
-
[h.Class(selectWrapperClassName)],
|
|
103
|
-
[
|
|
104
|
-
h.select(
|
|
105
|
-
[...attributes.select, h.Class(selectClassName)],
|
|
106
|
-
[
|
|
107
|
-
h.option([h.Value('us')], ['United States']),
|
|
108
|
-
h.option([h.Value('ca')], ['Canada']),
|
|
109
|
-
h.option([h.Value('gb')], ['United Kingdom']),
|
|
110
|
-
h.option([h.Value('au')], ['Australia']),
|
|
111
|
-
],
|
|
112
|
-
),
|
|
113
|
-
h.span(
|
|
114
|
-
[h.Class(chevronClassName)],
|
|
115
|
-
[Icon.chevronDown('w-4 h-4')],
|
|
116
|
-
),
|
|
117
|
-
],
|
|
118
|
-
),
|
|
119
|
-
h.span(
|
|
120
|
-
[...attributes.description, h.Class(descriptionClassName)],
|
|
121
|
-
['This select is disabled.'],
|
|
122
|
-
),
|
|
123
|
-
],
|
|
124
|
-
),
|
|
120
|
+
toView: disabledSelectView,
|
|
125
121
|
},
|
|
126
122
|
h,
|
|
127
123
|
),
|
|
@@ -42,11 +42,80 @@ const volumeFormatted = (value: number): string => `${Math.round(value * 100)}%`
|
|
|
42
42
|
|
|
43
43
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
44
44
|
(model, h): Html => {
|
|
45
|
+
const horizontalSliderView = (attributes: Slider.SliderAttributes): Html =>
|
|
46
|
+
h.div(
|
|
47
|
+
[h.Class(horizontalRowClassName)],
|
|
48
|
+
[
|
|
49
|
+
h.div(
|
|
50
|
+
[h.Class(horizontalHeaderClassName)],
|
|
51
|
+
[
|
|
52
|
+
h.label(
|
|
53
|
+
[...attributes.label, h.Class(labelClassName)],
|
|
54
|
+
['Rating'],
|
|
55
|
+
),
|
|
56
|
+
h.span(
|
|
57
|
+
[h.Class(valueClassName)],
|
|
58
|
+
[ratingFormatted(model.sliderRatingValue)],
|
|
59
|
+
),
|
|
60
|
+
],
|
|
61
|
+
),
|
|
62
|
+
h.div(
|
|
63
|
+
[...attributes.root, h.Class(horizontalRootClassName)],
|
|
64
|
+
[
|
|
65
|
+
h.div(
|
|
66
|
+
[...attributes.track, h.Class(horizontalTrackClassName)],
|
|
67
|
+
[
|
|
68
|
+
h.div([
|
|
69
|
+
...attributes.filledTrack,
|
|
70
|
+
h.Class(horizontalFilledTrackClassName),
|
|
71
|
+
]),
|
|
72
|
+
],
|
|
73
|
+
),
|
|
74
|
+
h.div([...attributes.thumb, h.Class(thumbClassName)]),
|
|
75
|
+
],
|
|
76
|
+
),
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const verticalSliderView = (attributes: Slider.SliderAttributes): Html =>
|
|
81
|
+
h.div(
|
|
82
|
+
[h.Class(verticalRowClassName)],
|
|
83
|
+
[
|
|
84
|
+
h.div(
|
|
85
|
+
[h.Class(verticalHeaderClassName)],
|
|
86
|
+
[
|
|
87
|
+
h.label(
|
|
88
|
+
[...attributes.label, h.Class(labelClassName)],
|
|
89
|
+
['Volume'],
|
|
90
|
+
),
|
|
91
|
+
h.span(
|
|
92
|
+
[h.Class(valueClassName)],
|
|
93
|
+
[volumeFormatted(model.sliderVolumeValue)],
|
|
94
|
+
),
|
|
95
|
+
],
|
|
96
|
+
),
|
|
97
|
+
h.div(
|
|
98
|
+
[...attributes.root, h.Class(verticalRootClassName)],
|
|
99
|
+
[
|
|
100
|
+
h.div(
|
|
101
|
+
[...attributes.track, h.Class(verticalTrackClassName)],
|
|
102
|
+
[
|
|
103
|
+
h.div([
|
|
104
|
+
...attributes.filledTrack,
|
|
105
|
+
h.Class(verticalFilledTrackClassName),
|
|
106
|
+
]),
|
|
107
|
+
],
|
|
108
|
+
),
|
|
109
|
+
h.div([...attributes.thumb, h.Class(thumbClassName)]),
|
|
110
|
+
],
|
|
111
|
+
),
|
|
112
|
+
],
|
|
113
|
+
)
|
|
114
|
+
|
|
45
115
|
return h.div(
|
|
46
116
|
[],
|
|
47
117
|
[
|
|
48
118
|
h.h2([h.Class('text-2xl font-bold text-gray-900 mb-6')], ['Slider']),
|
|
49
|
-
|
|
50
119
|
h.h3(
|
|
51
120
|
[h.Class('text-lg font-semibold text-gray-900 mt-8 mb-4')],
|
|
52
121
|
['Horizontal'],
|
|
@@ -58,43 +127,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
58
127
|
viewInputs: {
|
|
59
128
|
value: model.sliderRatingValue,
|
|
60
129
|
formatValue: value => `${value} of 10`,
|
|
61
|
-
toView:
|
|
62
|
-
h.div(
|
|
63
|
-
[h.Class(horizontalRowClassName)],
|
|
64
|
-
[
|
|
65
|
-
h.div(
|
|
66
|
-
[h.Class(horizontalHeaderClassName)],
|
|
67
|
-
[
|
|
68
|
-
h.label(
|
|
69
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
70
|
-
['Rating'],
|
|
71
|
-
),
|
|
72
|
-
h.span(
|
|
73
|
-
[h.Class(valueClassName)],
|
|
74
|
-
[ratingFormatted(model.sliderRatingValue)],
|
|
75
|
-
),
|
|
76
|
-
],
|
|
77
|
-
),
|
|
78
|
-
h.div(
|
|
79
|
-
[...attributes.root, h.Class(horizontalRootClassName)],
|
|
80
|
-
[
|
|
81
|
-
h.div(
|
|
82
|
-
[
|
|
83
|
-
...attributes.track,
|
|
84
|
-
h.Class(horizontalTrackClassName),
|
|
85
|
-
],
|
|
86
|
-
[
|
|
87
|
-
h.div([
|
|
88
|
-
...attributes.filledTrack,
|
|
89
|
-
h.Class(horizontalFilledTrackClassName),
|
|
90
|
-
]),
|
|
91
|
-
],
|
|
92
|
-
),
|
|
93
|
-
h.div([...attributes.thumb, h.Class(thumbClassName)]),
|
|
94
|
-
],
|
|
95
|
-
),
|
|
96
|
-
],
|
|
97
|
-
),
|
|
130
|
+
toView: horizontalSliderView,
|
|
98
131
|
},
|
|
99
132
|
toParentMessage: message =>
|
|
100
133
|
UiMessage.GotSliderRatingDemoMessage({ message }),
|
|
@@ -114,40 +147,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
114
147
|
thumbAlignment: 'Edge',
|
|
115
148
|
thumbSize: '1.25rem',
|
|
116
149
|
formatValue: value => `${Math.round(value * 100)} percent`,
|
|
117
|
-
toView:
|
|
118
|
-
h.div(
|
|
119
|
-
[h.Class(verticalRowClassName)],
|
|
120
|
-
[
|
|
121
|
-
h.div(
|
|
122
|
-
[h.Class(verticalHeaderClassName)],
|
|
123
|
-
[
|
|
124
|
-
h.label(
|
|
125
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
126
|
-
['Volume'],
|
|
127
|
-
),
|
|
128
|
-
h.span(
|
|
129
|
-
[h.Class(valueClassName)],
|
|
130
|
-
[volumeFormatted(model.sliderVolumeValue)],
|
|
131
|
-
),
|
|
132
|
-
],
|
|
133
|
-
),
|
|
134
|
-
h.div(
|
|
135
|
-
[...attributes.root, h.Class(verticalRootClassName)],
|
|
136
|
-
[
|
|
137
|
-
h.div(
|
|
138
|
-
[...attributes.track, h.Class(verticalTrackClassName)],
|
|
139
|
-
[
|
|
140
|
-
h.div([
|
|
141
|
-
...attributes.filledTrack,
|
|
142
|
-
h.Class(verticalFilledTrackClassName),
|
|
143
|
-
]),
|
|
144
|
-
],
|
|
145
|
-
),
|
|
146
|
-
h.div([...attributes.thumb, h.Class(thumbClassName)]),
|
|
147
|
-
],
|
|
148
|
-
),
|
|
149
|
-
],
|
|
150
|
-
),
|
|
150
|
+
toView: verticalSliderView,
|
|
151
151
|
},
|
|
152
152
|
toParentMessage: message =>
|
|
153
153
|
UiMessage.GotSliderVolumeDemoMessage({ message }),
|
|
@@ -32,6 +32,30 @@ const knob = (isChecked: boolean, h: HtmlBuilder<UiMessage>): Html => {
|
|
|
32
32
|
|
|
33
33
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
34
34
|
(model, h): Html => {
|
|
35
|
+
const switchView = (attributes: Switch.SwitchAttributes<UiMessage>): Html =>
|
|
36
|
+
h.div(
|
|
37
|
+
[h.Class(wrapperClassName)],
|
|
38
|
+
[
|
|
39
|
+
h.button(
|
|
40
|
+
[...attributes.button, h.Class(buttonClassName)],
|
|
41
|
+
[knob(model.isSwitchDemoChecked, h)],
|
|
42
|
+
),
|
|
43
|
+
h.div(
|
|
44
|
+
[],
|
|
45
|
+
[
|
|
46
|
+
h.label(
|
|
47
|
+
[...attributes.label, h.Class(labelClassName)],
|
|
48
|
+
['Enable notifications'],
|
|
49
|
+
),
|
|
50
|
+
h.p(
|
|
51
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
52
|
+
['Get notified when something important happens.'],
|
|
53
|
+
),
|
|
54
|
+
],
|
|
55
|
+
),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
35
59
|
return h.div(
|
|
36
60
|
[],
|
|
37
61
|
[
|
|
@@ -46,32 +70,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
46
70
|
hasDescription: true,
|
|
47
71
|
onToggle: isChecked =>
|
|
48
72
|
UiMessage.ToggledSwitchDemo({ isChecked }),
|
|
49
|
-
toView:
|
|
50
|
-
h.div(
|
|
51
|
-
[h.Class(wrapperClassName)],
|
|
52
|
-
[
|
|
53
|
-
h.button(
|
|
54
|
-
[...attributes.button, h.Class(buttonClassName)],
|
|
55
|
-
[knob(model.isSwitchDemoChecked, h)],
|
|
56
|
-
),
|
|
57
|
-
h.div(
|
|
58
|
-
[],
|
|
59
|
-
[
|
|
60
|
-
h.label(
|
|
61
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
62
|
-
['Enable notifications'],
|
|
63
|
-
),
|
|
64
|
-
h.p(
|
|
65
|
-
[
|
|
66
|
-
...attributes.description,
|
|
67
|
-
h.Class(descriptionClassName),
|
|
68
|
-
],
|
|
69
|
-
['Get notified when something important happens.'],
|
|
70
|
-
),
|
|
71
|
-
],
|
|
72
|
-
),
|
|
73
|
-
],
|
|
74
|
-
),
|
|
73
|
+
toView: switchView,
|
|
75
74
|
},
|
|
76
75
|
h,
|
|
77
76
|
),
|
|
@@ -96,6 +96,62 @@ const panelFor = (tab: DemoTab, h: HtmlBuilder<UiMessage>): Html =>
|
|
|
96
96
|
|
|
97
97
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
98
98
|
(model, h): Html => {
|
|
99
|
+
const horizontalTabsView = ({
|
|
100
|
+
tablist,
|
|
101
|
+
tabs,
|
|
102
|
+
activeIndex,
|
|
103
|
+
}: Tabs.RenderInfo<DemoTab>): Html =>
|
|
104
|
+
h.div(
|
|
105
|
+
[],
|
|
106
|
+
[
|
|
107
|
+
h.div(
|
|
108
|
+
[...tablist, h.Class('flex')],
|
|
109
|
+
tabs.map(tab =>
|
|
110
|
+
h.button(
|
|
111
|
+
[...tab.tab, h.Class(horizontalButtonClassName)],
|
|
112
|
+
[h.span([], [tab.value])],
|
|
113
|
+
),
|
|
114
|
+
),
|
|
115
|
+
),
|
|
116
|
+
...Array.map(
|
|
117
|
+
Array.filter(tabs, tab => tab.index === activeIndex),
|
|
118
|
+
tab =>
|
|
119
|
+
h.div(
|
|
120
|
+
[...tab.panel, h.Class(horizontalPanelClassName)],
|
|
121
|
+
[panelFor(tab.value, h)],
|
|
122
|
+
),
|
|
123
|
+
),
|
|
124
|
+
],
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
const verticalTabsView = ({
|
|
128
|
+
tablist,
|
|
129
|
+
tabs,
|
|
130
|
+
activeIndex,
|
|
131
|
+
}: Tabs.RenderInfo<DemoTab>): Html =>
|
|
132
|
+
h.div(
|
|
133
|
+
[h.Class('flex')],
|
|
134
|
+
[
|
|
135
|
+
h.div(
|
|
136
|
+
[...tablist, h.Class('flex flex-col')],
|
|
137
|
+
tabs.map(tab =>
|
|
138
|
+
h.button(
|
|
139
|
+
[...tab.tab, h.Class(verticalButtonClassName)],
|
|
140
|
+
[h.span([], [tab.value])],
|
|
141
|
+
),
|
|
142
|
+
),
|
|
143
|
+
),
|
|
144
|
+
...Array.map(
|
|
145
|
+
Array.filter(tabs, tab => tab.index === activeIndex),
|
|
146
|
+
tab =>
|
|
147
|
+
h.div(
|
|
148
|
+
[...tab.panel, h.Class(verticalPanelClassName)],
|
|
149
|
+
[panelFor(tab.value, h)],
|
|
150
|
+
),
|
|
151
|
+
),
|
|
152
|
+
],
|
|
153
|
+
)
|
|
154
|
+
|
|
99
155
|
return h.div(
|
|
100
156
|
[],
|
|
101
157
|
[
|
|
@@ -113,29 +169,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
113
169
|
tabs: demoTabs,
|
|
114
170
|
selectedValue: model.horizontalTabsDemoTab,
|
|
115
171
|
ariaLabel: 'Framework comparison tabs',
|
|
116
|
-
toView:
|
|
117
|
-
h.div(
|
|
118
|
-
[],
|
|
119
|
-
[
|
|
120
|
-
h.div(
|
|
121
|
-
[...tablist, h.Class('flex')],
|
|
122
|
-
tabs.map(tab =>
|
|
123
|
-
h.button(
|
|
124
|
-
[...tab.tab, h.Class(horizontalButtonClassName)],
|
|
125
|
-
[h.span([], [tab.value])],
|
|
126
|
-
),
|
|
127
|
-
),
|
|
128
|
-
),
|
|
129
|
-
...Array.map(
|
|
130
|
-
Array.filter(tabs, tab => tab.index === activeIndex),
|
|
131
|
-
tab =>
|
|
132
|
-
h.div(
|
|
133
|
-
[...tab.panel, h.Class(horizontalPanelClassName)],
|
|
134
|
-
[panelFor(tab.value, h)],
|
|
135
|
-
),
|
|
136
|
-
),
|
|
137
|
-
],
|
|
138
|
-
),
|
|
172
|
+
toView: horizontalTabsView,
|
|
139
173
|
},
|
|
140
174
|
toParentMessage: message =>
|
|
141
175
|
UiMessage.GotHorizontalTabsDemoMessage({ message }),
|
|
@@ -154,29 +188,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
154
188
|
selectedValue: model.verticalTabsDemoTab,
|
|
155
189
|
ariaLabel: 'Framework comparison tabs',
|
|
156
190
|
orientation: 'Vertical',
|
|
157
|
-
toView:
|
|
158
|
-
h.div(
|
|
159
|
-
[h.Class('flex')],
|
|
160
|
-
[
|
|
161
|
-
h.div(
|
|
162
|
-
[...tablist, h.Class('flex flex-col')],
|
|
163
|
-
tabs.map(tab =>
|
|
164
|
-
h.button(
|
|
165
|
-
[...tab.tab, h.Class(verticalButtonClassName)],
|
|
166
|
-
[h.span([], [tab.value])],
|
|
167
|
-
),
|
|
168
|
-
),
|
|
169
|
-
),
|
|
170
|
-
...Array.map(
|
|
171
|
-
Array.filter(tabs, tab => tab.index === activeIndex),
|
|
172
|
-
tab =>
|
|
173
|
-
h.div(
|
|
174
|
-
[...tab.panel, h.Class(verticalPanelClassName)],
|
|
175
|
-
[panelFor(tab.value, h)],
|
|
176
|
-
),
|
|
177
|
-
),
|
|
178
|
-
],
|
|
179
|
-
),
|
|
191
|
+
toView: verticalTabsView,
|
|
180
192
|
},
|
|
181
193
|
toParentMessage: message =>
|
|
182
194
|
UiMessage.GotVerticalTabsDemoMessage({ message }),
|