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
|
@@ -43,8 +43,21 @@ const sectionHeadingClassName = 'text-lg font-semibold text-gray-900 mt-8 mb-4'
|
|
|
43
43
|
const checkmark = (h: HtmlBuilder<UiMessage>): Html =>
|
|
44
44
|
h.span([h.Class('text-white text-xs')], ['✓'])
|
|
45
45
|
|
|
46
|
-
const nameInput = (value: string, h: HtmlBuilder<UiMessage>): Html =>
|
|
47
|
-
Input.
|
|
46
|
+
const nameInput = (value: string, h: HtmlBuilder<UiMessage>): Html => {
|
|
47
|
+
const nameInputView = (attributes: Input.InputAttributes<UiMessage>): Html =>
|
|
48
|
+
h.div(
|
|
49
|
+
[h.Class(fieldClassName)],
|
|
50
|
+
[
|
|
51
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
52
|
+
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
53
|
+
h.span(
|
|
54
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
55
|
+
['As it appears on your government-issued ID.'],
|
|
56
|
+
),
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return Input.view(
|
|
48
61
|
{
|
|
49
62
|
id: 'fieldset-name-input',
|
|
50
63
|
value,
|
|
@@ -52,24 +65,29 @@ const nameInput = (value: string, h: HtmlBuilder<UiMessage>): Html =>
|
|
|
52
65
|
onInput: inputValue =>
|
|
53
66
|
UiMessage.UpdatedFieldsetInputValue({ value: inputValue }),
|
|
54
67
|
placeholder: 'Enter your full name',
|
|
55
|
-
toView:
|
|
56
|
-
h.div(
|
|
57
|
-
[h.Class(fieldClassName)],
|
|
58
|
-
[
|
|
59
|
-
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
60
|
-
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
61
|
-
h.span(
|
|
62
|
-
[...attributes.description, h.Class(descriptionClassName)],
|
|
63
|
-
['As it appears on your government-issued ID.'],
|
|
64
|
-
),
|
|
65
|
-
],
|
|
66
|
-
),
|
|
68
|
+
toView: nameInputView,
|
|
67
69
|
},
|
|
68
70
|
h,
|
|
69
71
|
)
|
|
72
|
+
}
|
|
70
73
|
|
|
71
|
-
const bioTextarea = (value: string, h: HtmlBuilder<UiMessage>): Html =>
|
|
72
|
-
|
|
74
|
+
const bioTextarea = (value: string, h: HtmlBuilder<UiMessage>): Html => {
|
|
75
|
+
const bioTextareaView = (
|
|
76
|
+
attributes: Textarea.TextareaAttributes<UiMessage>,
|
|
77
|
+
): Html =>
|
|
78
|
+
h.div(
|
|
79
|
+
[h.Class(fieldClassName)],
|
|
80
|
+
[
|
|
81
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Bio']),
|
|
82
|
+
h.textarea([...attributes.textarea, h.Class(textareaClassName)]),
|
|
83
|
+
h.span(
|
|
84
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
85
|
+
['A brief introduction about yourself.'],
|
|
86
|
+
),
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return Textarea.view(
|
|
73
91
|
{
|
|
74
92
|
id: 'fieldset-bio-textarea',
|
|
75
93
|
value,
|
|
@@ -78,196 +96,207 @@ const bioTextarea = (value: string, h: HtmlBuilder<UiMessage>): Html =>
|
|
|
78
96
|
UiMessage.UpdatedFieldsetTextareaValue({ value: textareaValue }),
|
|
79
97
|
placeholder: 'Tell us about yourself...',
|
|
80
98
|
rows: 3,
|
|
81
|
-
toView:
|
|
99
|
+
toView: bioTextareaView,
|
|
100
|
+
},
|
|
101
|
+
h,
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const termsCheckbox = (isChecked: boolean, h: HtmlBuilder<UiMessage>): Html => {
|
|
106
|
+
const termsCheckboxView = (
|
|
107
|
+
attributes: Checkbox.CheckboxAttributes<UiMessage>,
|
|
108
|
+
): Html =>
|
|
109
|
+
h.div(
|
|
110
|
+
[h.Class('flex flex-col gap-1')],
|
|
111
|
+
[
|
|
82
112
|
h.div(
|
|
83
|
-
[h.Class(
|
|
113
|
+
[h.Class('flex items-center gap-2')],
|
|
84
114
|
[
|
|
85
|
-
h.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
115
|
+
h.button(
|
|
116
|
+
[...attributes.checkbox, h.Class(checkboxClassName)],
|
|
117
|
+
isChecked ? [checkmark(h)] : [],
|
|
118
|
+
),
|
|
119
|
+
h.label(
|
|
120
|
+
[...attributes.label, h.Class(checkboxLabelClassName)],
|
|
121
|
+
['I agree to the terms and conditions'],
|
|
90
122
|
),
|
|
91
123
|
],
|
|
92
124
|
),
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
125
|
+
h.p(
|
|
126
|
+
[...attributes.description, h.Class(checkboxDescriptionClassName)],
|
|
127
|
+
['You agree to our Terms of Service and Privacy Policy.'],
|
|
128
|
+
),
|
|
129
|
+
],
|
|
130
|
+
)
|
|
96
131
|
|
|
97
|
-
|
|
98
|
-
Checkbox.view(
|
|
132
|
+
return Checkbox.view(
|
|
99
133
|
{
|
|
100
134
|
id: FIELDSET_CHECKBOX_DEMO_ID,
|
|
101
135
|
isChecked,
|
|
102
136
|
hasDescription: true,
|
|
103
137
|
onToggle: nextIsChecked =>
|
|
104
138
|
UiMessage.ToggledFieldsetCheckboxDemo({ isChecked: nextIsChecked }),
|
|
105
|
-
toView:
|
|
106
|
-
h.div(
|
|
107
|
-
[h.Class('flex flex-col gap-1')],
|
|
108
|
-
[
|
|
109
|
-
h.div(
|
|
110
|
-
[h.Class('flex items-center gap-2')],
|
|
111
|
-
[
|
|
112
|
-
h.button(
|
|
113
|
-
[...attributes.checkbox, h.Class(checkboxClassName)],
|
|
114
|
-
isChecked ? [checkmark(h)] : [],
|
|
115
|
-
),
|
|
116
|
-
h.label(
|
|
117
|
-
[...attributes.label, h.Class(checkboxLabelClassName)],
|
|
118
|
-
['I agree to the terms and conditions'],
|
|
119
|
-
),
|
|
120
|
-
],
|
|
121
|
-
),
|
|
122
|
-
h.p(
|
|
123
|
-
[
|
|
124
|
-
...attributes.description,
|
|
125
|
-
h.Class(checkboxDescriptionClassName),
|
|
126
|
-
],
|
|
127
|
-
['You agree to our Terms of Service and Privacy Policy.'],
|
|
128
|
-
),
|
|
129
|
-
],
|
|
130
|
-
),
|
|
139
|
+
toView: termsCheckboxView,
|
|
131
140
|
},
|
|
132
141
|
h,
|
|
133
142
|
)
|
|
143
|
+
}
|
|
134
144
|
|
|
135
145
|
// DISABLED FIELDS
|
|
136
146
|
|
|
137
|
-
const disabledNameInput = (h: HtmlBuilder<UiMessage>): Html =>
|
|
138
|
-
|
|
147
|
+
const disabledNameInput = (h: HtmlBuilder<UiMessage>): Html => {
|
|
148
|
+
const disabledNameInputView = (
|
|
149
|
+
attributes: Input.InputAttributes<UiMessage>,
|
|
150
|
+
): Html =>
|
|
151
|
+
h.div(
|
|
152
|
+
[h.Class(fieldClassName)],
|
|
153
|
+
[
|
|
154
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
155
|
+
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
156
|
+
],
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return Input.view(
|
|
139
160
|
{
|
|
140
161
|
id: 'fieldset-disabled-name-input',
|
|
141
162
|
isDisabled: true,
|
|
142
163
|
value: 'Ada Lovelace',
|
|
143
|
-
toView:
|
|
144
|
-
h.div(
|
|
145
|
-
[h.Class(fieldClassName)],
|
|
146
|
-
[
|
|
147
|
-
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
148
|
-
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
149
|
-
],
|
|
150
|
-
),
|
|
164
|
+
toView: disabledNameInputView,
|
|
151
165
|
},
|
|
152
166
|
h,
|
|
153
167
|
)
|
|
168
|
+
}
|
|
154
169
|
|
|
155
|
-
const disabledBioTextarea = (h: HtmlBuilder<UiMessage>): Html =>
|
|
156
|
-
|
|
170
|
+
const disabledBioTextarea = (h: HtmlBuilder<UiMessage>): Html => {
|
|
171
|
+
const disabledBioTextareaView = (
|
|
172
|
+
attributes: Textarea.TextareaAttributes<UiMessage>,
|
|
173
|
+
): Html =>
|
|
174
|
+
h.div(
|
|
175
|
+
[h.Class(fieldClassName)],
|
|
176
|
+
[
|
|
177
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Bio']),
|
|
178
|
+
h.textarea([...attributes.textarea, h.Class(textareaClassName)]),
|
|
179
|
+
],
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return Textarea.view(
|
|
157
183
|
{
|
|
158
184
|
id: 'fieldset-disabled-bio-textarea',
|
|
159
185
|
isDisabled: true,
|
|
160
186
|
value:
|
|
161
187
|
"Mathematician and writer, known for work on Charles Babbage's Analytical Engine.",
|
|
162
188
|
rows: 3,
|
|
163
|
-
toView:
|
|
164
|
-
h.div(
|
|
165
|
-
[h.Class(fieldClassName)],
|
|
166
|
-
[
|
|
167
|
-
h.label([...attributes.label, h.Class(labelClassName)], ['Bio']),
|
|
168
|
-
h.textarea([...attributes.textarea, h.Class(textareaClassName)]),
|
|
169
|
-
],
|
|
170
|
-
),
|
|
189
|
+
toView: disabledBioTextareaView,
|
|
171
190
|
},
|
|
172
191
|
h,
|
|
173
192
|
)
|
|
193
|
+
}
|
|
174
194
|
|
|
175
|
-
const disabledTermsCheckbox = (h: HtmlBuilder<UiMessage>): Html =>
|
|
176
|
-
|
|
195
|
+
const disabledTermsCheckbox = (h: HtmlBuilder<UiMessage>): Html => {
|
|
196
|
+
const disabledTermsCheckboxView = (
|
|
197
|
+
attributes: Checkbox.CheckboxAttributes<UiMessage>,
|
|
198
|
+
): Html =>
|
|
199
|
+
h.div(
|
|
200
|
+
[h.Class('flex items-center gap-2')],
|
|
201
|
+
[
|
|
202
|
+
h.button(
|
|
203
|
+
[...attributes.checkbox, h.Class(checkboxClassName)],
|
|
204
|
+
[checkmark(h)],
|
|
205
|
+
),
|
|
206
|
+
h.label(
|
|
207
|
+
[...attributes.label, h.Class(checkboxLabelClassName)],
|
|
208
|
+
['I agree to the terms and conditions'],
|
|
209
|
+
),
|
|
210
|
+
],
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return Checkbox.view(
|
|
177
214
|
{
|
|
178
215
|
id: FIELDSET_DISABLED_CHECKBOX_ID,
|
|
179
216
|
isChecked: true,
|
|
180
217
|
isDisabled: true,
|
|
181
218
|
onToggle: isChecked =>
|
|
182
219
|
UiMessage.ToggledFieldsetCheckboxDemo({ isChecked }),
|
|
183
|
-
toView:
|
|
184
|
-
h.div(
|
|
185
|
-
[h.Class('flex items-center gap-2')],
|
|
186
|
-
[
|
|
187
|
-
h.button(
|
|
188
|
-
[...attributes.checkbox, h.Class(checkboxClassName)],
|
|
189
|
-
[checkmark(h)],
|
|
190
|
-
),
|
|
191
|
-
h.label(
|
|
192
|
-
[...attributes.label, h.Class(checkboxLabelClassName)],
|
|
193
|
-
['I agree to the terms and conditions'],
|
|
194
|
-
),
|
|
195
|
-
],
|
|
196
|
-
),
|
|
220
|
+
toView: disabledTermsCheckboxView,
|
|
197
221
|
},
|
|
198
222
|
h,
|
|
199
223
|
)
|
|
224
|
+
}
|
|
200
225
|
|
|
201
226
|
// DEMOS
|
|
202
227
|
|
|
203
|
-
const basicDemo = (model: UiModel, h: HtmlBuilder<UiMessage>): Html =>
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
228
|
+
const basicDemo = (model: UiModel, h: HtmlBuilder<UiMessage>): Html => {
|
|
229
|
+
const basicFieldsetView = (
|
|
230
|
+
attributes: Fieldset.FieldsetAttributes<UiMessage>,
|
|
231
|
+
): Html =>
|
|
232
|
+
h.fieldset(
|
|
233
|
+
[...attributes.fieldset, h.Class(fieldsetClassName)],
|
|
234
|
+
[
|
|
235
|
+
h.legend(
|
|
236
|
+
[...attributes.legend, h.Class(legendClassName)],
|
|
237
|
+
['Personal Information'],
|
|
238
|
+
),
|
|
239
|
+
h.span(
|
|
240
|
+
[...attributes.description, h.Class(`${descriptionClassName} mt-1`)],
|
|
241
|
+
['We just need a few details.'],
|
|
242
|
+
),
|
|
243
|
+
h.div(
|
|
244
|
+
[h.Class(fieldsClassName)],
|
|
211
245
|
[
|
|
212
|
-
h
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
),
|
|
216
|
-
h.span(
|
|
217
|
-
[
|
|
218
|
-
...attributes.description,
|
|
219
|
-
h.Class(`${descriptionClassName} mt-1`),
|
|
220
|
-
],
|
|
221
|
-
['We just need a few details.'],
|
|
222
|
-
),
|
|
223
|
-
h.div(
|
|
224
|
-
[h.Class(fieldsClassName)],
|
|
225
|
-
[
|
|
226
|
-
nameInput(model.fieldsetInputValue, h),
|
|
227
|
-
bioTextarea(model.fieldsetTextareaValue, h),
|
|
228
|
-
termsCheckbox(model.isFieldsetCheckboxDemoChecked, h),
|
|
229
|
-
],
|
|
230
|
-
),
|
|
246
|
+
nameInput(model.fieldsetInputValue, h),
|
|
247
|
+
bioTextarea(model.fieldsetTextareaValue, h),
|
|
248
|
+
termsCheckbox(model.isFieldsetCheckboxDemoChecked, h),
|
|
231
249
|
],
|
|
232
250
|
),
|
|
251
|
+
],
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return Fieldset.view(
|
|
255
|
+
{
|
|
256
|
+
id: 'fieldset-basic-demo',
|
|
257
|
+
hasDescription: true,
|
|
258
|
+
toView: basicFieldsetView,
|
|
233
259
|
},
|
|
234
260
|
h,
|
|
235
261
|
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const disabledDemo = (h: HtmlBuilder<UiMessage>): Html => {
|
|
265
|
+
const disabledFieldsetView = (
|
|
266
|
+
attributes: Fieldset.FieldsetAttributes<UiMessage>,
|
|
267
|
+
): Html =>
|
|
268
|
+
h.fieldset(
|
|
269
|
+
[...attributes.fieldset, h.Class(fieldsetClassName)],
|
|
270
|
+
[
|
|
271
|
+
h.legend(
|
|
272
|
+
[...attributes.legend, h.Class(legendClassName)],
|
|
273
|
+
['Personal Information'],
|
|
274
|
+
),
|
|
275
|
+
h.span(
|
|
276
|
+
[...attributes.description, h.Class(`${descriptionClassName} mt-1`)],
|
|
277
|
+
['This fieldset is disabled.'],
|
|
278
|
+
),
|
|
279
|
+
h.div(
|
|
280
|
+
[h.Class(fieldsClassName)],
|
|
281
|
+
[
|
|
282
|
+
disabledNameInput(h),
|
|
283
|
+
disabledBioTextarea(h),
|
|
284
|
+
disabledTermsCheckbox(h),
|
|
285
|
+
],
|
|
286
|
+
),
|
|
287
|
+
],
|
|
288
|
+
)
|
|
236
289
|
|
|
237
|
-
|
|
238
|
-
Fieldset.view(
|
|
290
|
+
return Fieldset.view(
|
|
239
291
|
{
|
|
240
292
|
id: 'fieldset-disabled-demo',
|
|
241
293
|
isDisabled: true,
|
|
242
294
|
hasDescription: true,
|
|
243
|
-
toView:
|
|
244
|
-
h.fieldset(
|
|
245
|
-
[...attributes.fieldset, h.Class(fieldsetClassName)],
|
|
246
|
-
[
|
|
247
|
-
h.legend(
|
|
248
|
-
[...attributes.legend, h.Class(legendClassName)],
|
|
249
|
-
['Personal Information'],
|
|
250
|
-
),
|
|
251
|
-
h.span(
|
|
252
|
-
[
|
|
253
|
-
...attributes.description,
|
|
254
|
-
h.Class(`${descriptionClassName} mt-1`),
|
|
255
|
-
],
|
|
256
|
-
['This fieldset is disabled.'],
|
|
257
|
-
),
|
|
258
|
-
h.div(
|
|
259
|
-
[h.Class(fieldsClassName)],
|
|
260
|
-
[
|
|
261
|
-
disabledNameInput(h),
|
|
262
|
-
disabledBioTextarea(h),
|
|
263
|
-
disabledTermsCheckbox(h),
|
|
264
|
-
],
|
|
265
|
-
),
|
|
266
|
-
],
|
|
267
|
-
),
|
|
295
|
+
toView: disabledFieldsetView,
|
|
268
296
|
},
|
|
269
297
|
h,
|
|
270
298
|
)
|
|
299
|
+
}
|
|
271
300
|
|
|
272
301
|
// VIEW
|
|
273
302
|
|
|
@@ -42,6 +42,22 @@ const fileKey = (file: File.File): string =>
|
|
|
42
42
|
|
|
43
43
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
44
44
|
(model, h): Html => {
|
|
45
|
+
const fileDropView = (attributes: FileDrop.FileDropAttributes): Html =>
|
|
46
|
+
h.label(
|
|
47
|
+
[...attributes.root, h.Class(dropZoneClassName)],
|
|
48
|
+
[
|
|
49
|
+
h.p(
|
|
50
|
+
[h.Class(primaryTextClassName)],
|
|
51
|
+
['Drop files or click to browse'],
|
|
52
|
+
),
|
|
53
|
+
h.p(
|
|
54
|
+
[h.Class(secondaryTextClassName)],
|
|
55
|
+
['Any file type. This demo just lists them.'],
|
|
56
|
+
),
|
|
57
|
+
h.input(attributes.input),
|
|
58
|
+
],
|
|
59
|
+
)
|
|
60
|
+
|
|
45
61
|
return h.div(
|
|
46
62
|
[],
|
|
47
63
|
[
|
|
@@ -55,21 +71,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
55
71
|
view: FileDrop.view,
|
|
56
72
|
viewInputs: {
|
|
57
73
|
multiple: true,
|
|
58
|
-
toView:
|
|
59
|
-
h.label(
|
|
60
|
-
[...attributes.root, h.Class(dropZoneClassName)],
|
|
61
|
-
[
|
|
62
|
-
h.p(
|
|
63
|
-
[h.Class(primaryTextClassName)],
|
|
64
|
-
['Drop files or click to browse'],
|
|
65
|
-
),
|
|
66
|
-
h.p(
|
|
67
|
-
[h.Class(secondaryTextClassName)],
|
|
68
|
-
['Any file type. This demo just lists them.'],
|
|
69
|
-
),
|
|
70
|
-
h.input(attributes.input),
|
|
71
|
-
],
|
|
72
|
-
),
|
|
74
|
+
toView: fileDropView,
|
|
73
75
|
},
|
|
74
76
|
toParentMessage: message =>
|
|
75
77
|
UiMessage.GotFileDropBasicDemoMessage({ message }),
|
|
@@ -15,64 +15,72 @@ const panelClassName =
|
|
|
15
15
|
const TRIGGER_ID = 'hover-intent-showcase-trigger'
|
|
16
16
|
const PANEL_ID = 'hover-intent-showcase-panel'
|
|
17
17
|
|
|
18
|
-
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
19
|
-
h
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[h.Class('mb-4 max-w-xl text-sm text-gray-600')],
|
|
18
|
+
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
19
|
+
(model, h): Html => {
|
|
20
|
+
const hoverIntentView = ({
|
|
21
|
+
trigger,
|
|
22
|
+
panel,
|
|
23
|
+
isVisible,
|
|
24
|
+
}: HoverIntent.RenderInfo): Html =>
|
|
25
|
+
h.div(
|
|
26
|
+
[h.Class('relative inline-block')],
|
|
28
27
|
[
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
h.
|
|
28
|
+
h.button(
|
|
29
|
+
[
|
|
30
|
+
...trigger,
|
|
31
|
+
h.Type('button'),
|
|
32
|
+
h.Id(TRIGGER_ID),
|
|
33
|
+
h.AriaControls(PANEL_ID),
|
|
34
|
+
h.AriaExpanded(isVisible),
|
|
35
|
+
h.Class(triggerClassName),
|
|
36
|
+
],
|
|
37
|
+
['More information'],
|
|
38
|
+
),
|
|
39
|
+
...(isVisible
|
|
40
|
+
? [
|
|
41
|
+
h.div(
|
|
42
|
+
[...panel, h.Id(PANEL_ID), h.Class(panelClassName)],
|
|
43
43
|
[
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
h.
|
|
49
|
-
|
|
44
|
+
h.h3(
|
|
45
|
+
[h.Class('text-sm font-medium text-gray-900')],
|
|
46
|
+
['Details'],
|
|
47
|
+
),
|
|
48
|
+
h.p(
|
|
49
|
+
[h.Class('mt-1 text-sm leading-5 text-gray-600')],
|
|
50
|
+
['A short description can provide useful context.'],
|
|
51
|
+
),
|
|
50
52
|
],
|
|
51
|
-
['More information'],
|
|
52
53
|
),
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
54
|
+
]
|
|
55
|
+
: []),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return h.div(
|
|
60
|
+
[],
|
|
61
|
+
[
|
|
62
|
+
h.h2(
|
|
63
|
+
[h.Class('text-2xl font-bold text-gray-900 mb-6')],
|
|
64
|
+
['Hover Intent'],
|
|
65
|
+
),
|
|
66
|
+
h.p(
|
|
67
|
+
[h.Class('mb-4 max-w-xl text-sm text-gray-600')],
|
|
68
|
+
[
|
|
69
|
+
'Hover over or focus the “More information” trigger, then move the pointer into the card. Move the pointer or focus away from both elements, or press Escape, to close it.',
|
|
70
|
+
],
|
|
71
|
+
),
|
|
72
|
+
h.submodel({
|
|
73
|
+
slotId: 'hover-intent-showcase',
|
|
74
|
+
model: model.hoverIntentDemo,
|
|
75
|
+
view: HoverIntent.view,
|
|
76
|
+
viewInputs: {
|
|
77
|
+
focusTriggerSelector: `#${TRIGGER_ID}`,
|
|
78
|
+
toView: hoverIntentView,
|
|
79
|
+
},
|
|
80
|
+
toParentMessage: message =>
|
|
81
|
+
UiMessage.GotHoverIntentDemoMessage({ message }),
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
)
|
|
85
|
+
},
|
|
78
86
|
)
|
|
@@ -15,6 +15,36 @@ const descriptionClassName = 'text-sm text-gray-500'
|
|
|
15
15
|
|
|
16
16
|
export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
17
17
|
(model, h): Html => {
|
|
18
|
+
const basicInputView = (
|
|
19
|
+
attributes: Input.InputAttributes<UiMessage>,
|
|
20
|
+
): Html =>
|
|
21
|
+
h.div(
|
|
22
|
+
[h.Class('flex flex-col gap-1.5 w-full')],
|
|
23
|
+
[
|
|
24
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
25
|
+
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
26
|
+
h.span(
|
|
27
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
28
|
+
['As it appears on your government-issued ID.'],
|
|
29
|
+
),
|
|
30
|
+
],
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const disabledInputView = (
|
|
34
|
+
attributes: Input.InputAttributes<UiMessage>,
|
|
35
|
+
): Html =>
|
|
36
|
+
h.div(
|
|
37
|
+
[h.Class('flex flex-col gap-1.5 max-w-sm')],
|
|
38
|
+
[
|
|
39
|
+
h.label([...attributes.label, h.Class(labelClassName)], ['Name']),
|
|
40
|
+
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
41
|
+
h.span(
|
|
42
|
+
[...attributes.description, h.Class(descriptionClassName)],
|
|
43
|
+
['This input is disabled.'],
|
|
44
|
+
),
|
|
45
|
+
],
|
|
46
|
+
)
|
|
47
|
+
|
|
18
48
|
return h.div(
|
|
19
49
|
[],
|
|
20
50
|
[
|
|
@@ -34,24 +64,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
34
64
|
hasDescription: true,
|
|
35
65
|
onInput: value => UiMessage.UpdatedInputDemoValue({ value }),
|
|
36
66
|
placeholder: 'Enter your full name',
|
|
37
|
-
toView:
|
|
38
|
-
h.div(
|
|
39
|
-
[h.Class('flex flex-col gap-1.5 w-full')],
|
|
40
|
-
[
|
|
41
|
-
h.label(
|
|
42
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
43
|
-
['Name'],
|
|
44
|
-
),
|
|
45
|
-
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
46
|
-
h.span(
|
|
47
|
-
[
|
|
48
|
-
...attributes.description,
|
|
49
|
-
h.Class(descriptionClassName),
|
|
50
|
-
],
|
|
51
|
-
['As it appears on your government-issued ID.'],
|
|
52
|
-
),
|
|
53
|
-
],
|
|
54
|
-
),
|
|
67
|
+
toView: basicInputView,
|
|
55
68
|
},
|
|
56
69
|
h,
|
|
57
70
|
),
|
|
@@ -68,21 +81,7 @@ export const view = Submodel.defineView<UiModel, UiMessage>(
|
|
|
68
81
|
isDisabled: true,
|
|
69
82
|
hasDescription: true,
|
|
70
83
|
value: 'Ada Lovelace',
|
|
71
|
-
toView:
|
|
72
|
-
h.div(
|
|
73
|
-
[h.Class('flex flex-col gap-1.5 max-w-sm')],
|
|
74
|
-
[
|
|
75
|
-
h.label(
|
|
76
|
-
[...attributes.label, h.Class(labelClassName)],
|
|
77
|
-
['Name'],
|
|
78
|
-
),
|
|
79
|
-
h.input([...attributes.input, h.Class(inputClassName)]),
|
|
80
|
-
h.span(
|
|
81
|
-
[...attributes.description, h.Class(descriptionClassName)],
|
|
82
|
-
['This input is disabled.'],
|
|
83
|
-
),
|
|
84
|
-
],
|
|
85
|
-
),
|
|
84
|
+
toView: disabledInputView,
|
|
86
85
|
},
|
|
87
86
|
h,
|
|
88
87
|
),
|