@jsenv/navi 0.0.1 → 0.1.1

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.
Files changed (139) hide show
  1. package/dist/jsenv_navi.js +22959 -0
  2. package/index.js +66 -16
  3. package/package.json +23 -11
  4. package/src/actions.js +50 -26
  5. package/src/browser_integration/browser_integration.js +31 -6
  6. package/src/browser_integration/via_history.js +42 -9
  7. package/src/components/action_execution/render_actionable_component.jsx +6 -4
  8. package/src/components/action_execution/use_action.js +51 -282
  9. package/src/components/action_execution/use_execute_action.js +106 -92
  10. package/src/components/action_execution/use_run_on_mount.js +9 -0
  11. package/src/components/action_renderer.jsx +21 -32
  12. package/src/components/demos/0_button_demo.html +574 -103
  13. package/src/components/demos/10_column_reordering_debug.html +277 -0
  14. package/src/components/demos/11_table_selection_debug.html +432 -0
  15. package/src/components/demos/1_checkbox_demo.html +579 -202
  16. package/src/components/demos/2_input_textual_demo.html +81 -138
  17. package/src/components/demos/3_radio_demo.html +0 -2
  18. package/src/components/demos/4_select_demo.html +19 -23
  19. package/src/components/demos/6_tablist_demo.html +77 -0
  20. package/src/components/demos/7_table_selection_demo.html +176 -0
  21. package/src/components/demos/8_table_fixed_headers_demo.html +584 -0
  22. package/src/components/demos/9_table_column_drag_demo.html +325 -0
  23. package/src/components/demos/action/0_button_demo.html +2 -4
  24. package/src/components/demos/action/1_input_text_demo.html +643 -222
  25. package/src/components/demos/action/3_details_demo.html +146 -115
  26. package/src/components/demos/action/4_input_checkbox_demo.html +442 -322
  27. package/src/components/demos/action/5_input_checkbox_state_demo.html +270 -0
  28. package/src/components/demos/action/6_checkbox_list_demo.html +304 -72
  29. package/src/components/demos/action/7_radio_list_demo.html +310 -170
  30. package/src/components/demos/action/{8_editable_text_demo.html → 8_editable_demo.html} +65 -76
  31. package/src/components/demos/action/9_link_demo.html +84 -62
  32. package/src/components/demos/ui_transition/0_action_renderer_ui_transition_demo.html +695 -0
  33. package/src/components/demos/ui_transition/1_nested_ui_transition_demo.html +429 -0
  34. package/src/components/demos/ui_transition/2_height_transition_test.html +295 -0
  35. package/src/components/details/details.jsx +62 -64
  36. package/src/components/edition/editable.jsx +186 -0
  37. package/src/components/field/README.md +247 -0
  38. package/src/components/{input → field}/button.jsx +151 -130
  39. package/src/components/field/checkbox_list.jsx +184 -0
  40. package/src/components/{collect_form_element_values.js → field/collect_form_element_values.js} +7 -4
  41. package/src/components/{input → field}/field_css.js +4 -1
  42. package/src/components/field/form.jsx +211 -0
  43. package/src/components/{input → field}/input.jsx +1 -0
  44. package/src/components/{input → field}/input_checkbox.jsx +132 -155
  45. package/src/components/{input → field}/input_radio.jsx +135 -46
  46. package/src/components/field/input_textual.jsx +418 -0
  47. package/src/components/field/label.jsx +32 -0
  48. package/src/components/field/radio_list.jsx +182 -0
  49. package/src/components/{input → field}/select.jsx +17 -32
  50. package/src/components/field/use_action_events.js +132 -0
  51. package/src/components/field/use_form_events.js +55 -0
  52. package/src/components/field/use_ui_state_controller.js +506 -0
  53. package/src/components/item_tracker/README.md +461 -0
  54. package/src/components/item_tracker/use_isolated_item_tracker.jsx +209 -0
  55. package/src/components/item_tracker/use_isolated_item_tracker_demo.html +148 -0
  56. package/src/components/item_tracker/use_isolated_item_tracker_demo.jsx +460 -0
  57. package/src/components/item_tracker/use_item_tracker.jsx +143 -0
  58. package/src/components/item_tracker/use_item_tracker_demo.html +207 -0
  59. package/src/components/item_tracker/use_item_tracker_demo.jsx +216 -0
  60. package/src/components/keyboard_shortcuts/active_keyboard_shortcuts.jsx +87 -0
  61. package/src/components/keyboard_shortcuts/aria_key_shortcuts.js +61 -0
  62. package/src/components/keyboard_shortcuts/keyboard_key_meta.js +17 -0
  63. package/src/components/keyboard_shortcuts/keyboard_shortcuts.js +371 -0
  64. package/src/components/link/link.jsx +65 -102
  65. package/src/components/link/link_with_icon.jsx +52 -0
  66. package/src/components/loader/loader_background.jsx +85 -64
  67. package/src/components/loader/rectangle_loading.jsx +38 -19
  68. package/src/components/route.jsx +8 -4
  69. package/src/components/selection/selection.jsx +1583 -0
  70. package/src/components/svg/font_sized_svg.jsx +45 -0
  71. package/src/components/svg/icon_and_text.jsx +21 -0
  72. package/src/components/svg/svg_mask_overlay.jsx +105 -0
  73. package/src/components/table/drag/table_drag.jsx +506 -0
  74. package/src/components/table/resize/table_resize.jsx +650 -0
  75. package/src/components/table/resize/table_size.js +43 -0
  76. package/src/components/table/selection/table_selection.js +106 -0
  77. package/src/components/table/selection/table_selection.jsx +203 -0
  78. package/src/components/table/sticky/sticky_group.js +354 -0
  79. package/src/components/table/sticky/table_sticky.js +25 -0
  80. package/src/components/table/sticky/table_sticky.jsx +501 -0
  81. package/src/components/table/table.jsx +721 -0
  82. package/src/components/table/table_css.js +211 -0
  83. package/src/components/table/table_ui.jsx +49 -0
  84. package/src/components/table/use_cells_and_columns.js +90 -0
  85. package/src/components/table/use_object_array_to_cells.js +46 -0
  86. package/src/components/table/z_indexes.js +23 -0
  87. package/src/components/tablist/tablist.jsx +99 -0
  88. package/src/components/text/overflow.jsx +15 -0
  89. package/src/components/text/text_and_count.jsx +28 -0
  90. package/src/components/ui_transition.jsx +128 -0
  91. package/src/components/use_auto_focus.js +58 -7
  92. package/src/components/use_batch_during_render.js +33 -0
  93. package/src/components/use_debounce_true.js +7 -7
  94. package/src/components/use_dependencies_diff.js +35 -0
  95. package/src/components/use_focus_group.js +4 -3
  96. package/src/components/use_initial_value.js +8 -34
  97. package/src/components/use_signal_sync.js +1 -1
  98. package/src/components/use_stable_callback.js +68 -0
  99. package/src/components/use_state_array.js +16 -9
  100. package/src/docs/actions.md +22 -0
  101. package/src/notes.md +33 -12
  102. package/src/route/route.js +97 -47
  103. package/src/store/resource_graph.js +2 -1
  104. package/src/store/tests/{resource_graph_dependencies.test.js → resource_graph_dependencies.test_manual.js} +13 -13
  105. package/src/utils/is_signal.js +20 -0
  106. package/src/utils/stringify_for_display.js +4 -23
  107. package/src/validation/constraints/confirm_constraint.js +14 -0
  108. package/src/validation/constraints/create_unique_value_constraint.js +27 -0
  109. package/src/validation/constraints/native_constraints.js +313 -0
  110. package/src/validation/constraints/readonly_constraint.js +36 -0
  111. package/src/validation/constraints/single_space_constraint.js +13 -0
  112. package/src/validation/custom_constraint_validation.js +599 -0
  113. package/src/validation/custom_message.js +18 -0
  114. package/src/validation/demos/browser_style.png +0 -0
  115. package/src/validation/demos/form_validation_demo.html +142 -0
  116. package/src/validation/demos/form_validation_demo_preact.html +87 -0
  117. package/src/validation/demos/form_validation_native_popover_demo.html +168 -0
  118. package/src/validation/demos/form_validation_vs_native_demo.html +172 -0
  119. package/src/validation/demos/validation_message_demo.html +203 -0
  120. package/src/validation/hooks/use_constraints.js +23 -0
  121. package/src/validation/hooks/use_custom_validation_ref.js +73 -0
  122. package/src/validation/hooks/use_validation_message.js +19 -0
  123. package/src/validation/validation_message.js +741 -0
  124. package/src/components/editable_text/editable_text.jsx +0 -96
  125. package/src/components/form.jsx +0 -144
  126. package/src/components/input/checkbox_list.jsx +0 -294
  127. package/src/components/input/field.jsx +0 -61
  128. package/src/components/input/input_textual.jsx +0 -338
  129. package/src/components/input/radio_list.jsx +0 -283
  130. package/src/components/input/use_form_event.js +0 -20
  131. package/src/components/input/use_on_change.js +0 -12
  132. package/src/components/selection/selection.js +0 -5
  133. package/src/components/selection/selection_context.jsx +0 -262
  134. package/src/components/shortcut/shortcut_context.jsx +0 -390
  135. package/src/components/use_action_events.js +0 -37
  136. package/src/utils/iterable_weak_set.js +0 -62
  137. /package/src/components/demos/action/{11_nested_shortcuts_demo.html → 11_nested_shortcuts_demo.xhtml} +0 -0
  138. /package/src/components/{shortcut → keyboard_shortcuts}/os.js +0 -0
  139. /package/src/route/{route.test.html → route.xtest.html} +0 -0
@@ -4,10 +4,303 @@
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" href="data:," />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Checkbox demo</title>
7
+ <title>Checkbox Demo</title>
8
+ <style>
9
+ body {
10
+ font-family:
11
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
12
+ max-width: 1400px;
13
+ margin: 0 auto;
14
+ padding: 20px;
15
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
16
+ min-height: 100vh;
17
+ }
18
+
19
+ h1 {
20
+ text-align: center;
21
+ color: #2c3e50;
22
+ margin-bottom: 30px;
23
+ font-size: 2.5rem;
24
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
25
+ }
26
+
27
+ .demo-grid {
28
+ display: grid;
29
+ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
30
+ gap: 20px;
31
+ margin-bottom: 30px;
32
+ }
33
+
34
+ .demo-card {
35
+ background: white;
36
+ border-radius: 12px;
37
+ padding: 25px;
38
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
39
+ border: 1px solid #e1e8ed;
40
+ transition:
41
+ transform 0.2s ease,
42
+ box-shadow 0.2s ease;
43
+ }
44
+
45
+ .demo-card:hover {
46
+ transform: translateY(-2px);
47
+ box-shadow: 0 12px 35px rgba(0, 0, 0, 0.15);
48
+ }
49
+
50
+ .demo-title {
51
+ color: #2c3e50;
52
+ margin: 0 0 20px 0;
53
+ font-size: 1.3rem;
54
+ font-weight: 600;
55
+ border-bottom: 3px solid #3498db;
56
+ padding-bottom: 10px;
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 10px;
60
+ }
61
+
62
+ .demo-title::before {
63
+ content: "✨";
64
+ font-size: 1.2rem;
65
+ }
66
+
67
+ .checkbox-row {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 15px;
71
+ margin: 15px 0;
72
+ padding: 12px;
73
+ background: #f8f9fa;
74
+ border-radius: 8px;
75
+ border: 1px solid #e9ecef;
76
+ transition: background 0.2s ease;
77
+ }
78
+
79
+ .checkbox-row:hover {
80
+ background: #e8f4f8;
81
+ }
82
+
83
+ .checkbox-label {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 10px;
87
+ font-size: 1rem;
88
+ color: #495057;
89
+ cursor: pointer;
90
+ flex: 1;
91
+ min-width: 0;
92
+ }
93
+
94
+ .toggle-button {
95
+ padding: 8px 16px;
96
+ background: linear-gradient(45deg, #3498db, #2980b9);
97
+ color: white;
98
+ border: none;
99
+ border-radius: 6px;
100
+ cursor: pointer;
101
+ font-size: 0.9rem;
102
+ font-weight: 500;
103
+ transition: all 0.2s ease;
104
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
105
+ flex-shrink: 0;
106
+ white-space: nowrap;
107
+ }
108
+
109
+ .toggle-button:hover {
110
+ background: linear-gradient(45deg, #2980b9, #1f6591);
111
+ transform: translateY(-1px);
112
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
113
+ }
114
+
115
+ .comparison {
116
+ display: flex;
117
+ flex-direction: column;
118
+ gap: 8px;
119
+ margin-top: 15px;
120
+ padding: 12px;
121
+ background: #fff3cd;
122
+ border-radius: 6px;
123
+ border-left: 4px solid #ffc107;
124
+ }
125
+
126
+ .comparison-label {
127
+ font-size: 0.85rem;
128
+ color: #856404;
129
+ font-weight: 500;
130
+ margin-bottom: 5px;
131
+ }
132
+
133
+ .native-examples {
134
+ display: flex;
135
+ flex-direction: column;
136
+ gap: 8px;
137
+ }
138
+
139
+ .native-examples label {
140
+ display: flex;
141
+ align-items: center;
142
+ gap: 10px;
143
+ font-size: 0.9rem;
144
+ color: #495057;
145
+ }
146
+
147
+ .prop-control-demo {
148
+ grid-column: 1 / -1;
149
+ background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
150
+ color: white;
151
+ }
152
+
153
+ .prop-control-demo .demo-title {
154
+ color: white;
155
+ border-bottom-color: #ffffff;
156
+ }
157
+
158
+ .prop-control-demo .demo-title::before {
159
+ content: "�️";
160
+ }
161
+
162
+ .color-controls {
163
+ margin-bottom: 25px;
164
+ display: grid;
165
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
166
+ gap: 15px;
167
+ }
168
+
169
+ .color-select-group {
170
+ background: rgba(255, 255, 255, 0.1);
171
+ padding: 15px;
172
+ border-radius: 8px;
173
+ border: 1px solid rgba(255, 255, 255, 0.2);
174
+ }
175
+
176
+ .color-select-label {
177
+ display: block;
178
+ margin-bottom: 8px;
179
+ font-weight: 500;
180
+ font-size: 0.95rem;
181
+ }
182
+
183
+ .color-select {
184
+ width: 100%;
185
+ padding: 8px 12px;
186
+ border: none;
187
+ border-radius: 6px;
188
+ background: white;
189
+ color: #333;
190
+ font-size: 0.9rem;
191
+ cursor: pointer;
192
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
193
+ }
194
+
195
+ .state-controls {
196
+ background: rgba(255, 255, 255, 0.1);
197
+ padding: 15px;
198
+ border-radius: 8px;
199
+ border: 1px solid rgba(255, 255, 255, 0.2);
200
+ margin-bottom: 20px;
201
+ }
202
+
203
+ .state-controls h4 {
204
+ margin: 0 0 15px 0;
205
+ font-size: 1rem;
206
+ color: white;
207
+ }
208
+
209
+ .control-row {
210
+ display: flex;
211
+ gap: 15px;
212
+ flex-wrap: wrap;
213
+ margin-bottom: 10px;
214
+ }
215
+
216
+ .control-group {
217
+ display: flex;
218
+ flex-direction: column;
219
+ align-items: center;
220
+ gap: 8px;
221
+ background: rgba(255, 255, 255, 0.05);
222
+ padding: 12px;
223
+ border-radius: 8px;
224
+ border: 1px solid rgba(255, 255, 255, 0.1);
225
+ min-width: 100px;
226
+ }
227
+
228
+ .control-toggle {
229
+ padding: 8px 16px;
230
+ border: 2px solid rgba(255, 255, 255, 0.3);
231
+ background: rgba(255, 255, 255, 0.1);
232
+ color: white;
233
+ border-radius: 6px;
234
+ cursor: pointer;
235
+ font-size: 0.85rem;
236
+ font-weight: 500;
237
+ transition: all 0.2s ease;
238
+ min-width: 80px;
239
+ text-align: center;
240
+ }
241
+
242
+ .control-toggle.active {
243
+ background: rgba(255, 255, 255, 0.9);
244
+ color: #333;
245
+ border-color: white;
246
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
247
+ }
248
+
249
+ .control-toggle:hover {
250
+ background: rgba(255, 255, 255, 0.2);
251
+ border-color: rgba(255, 255, 255, 0.5);
252
+ }
253
+
254
+ .control-toggle.active:hover {
255
+ background: white;
256
+ }
257
+
258
+ .control-label {
259
+ font-size: 0.9rem;
260
+ color: white;
261
+ margin: 0;
262
+ }
263
+
264
+ .accent-checkbox-grid {
265
+ display: grid;
266
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
267
+ gap: 15px;
268
+ background: rgba(255, 255, 255, 0.1);
269
+ padding: 20px;
270
+ border-radius: 8px;
271
+ border: 1px solid rgba(255, 255, 255, 0.2);
272
+ }
273
+
274
+ .accent-checkbox-item {
275
+ display: flex;
276
+ align-items: center;
277
+ gap: 10px;
278
+ padding: 10px;
279
+ background: rgba(255, 255, 255, 0.05);
280
+ border-radius: 6px;
281
+ font-size: 0.95rem;
282
+ }
283
+
284
+ @media (max-width: 768px) {
285
+ .demo-grid {
286
+ grid-template-columns: 1fr;
287
+ }
288
+
289
+ h1 {
290
+ font-size: 2rem;
291
+ }
292
+
293
+ .checkbox-row {
294
+ flex-direction: column;
295
+ align-items: stretch;
296
+ gap: 10px;
297
+ }
298
+ }
299
+ </style>
8
300
  </head>
9
301
  <body>
10
- <div id="root" style="position: relative"></div>
302
+ <h1>🎛️ Interactive Checkbox Demo</h1>
303
+ <div id="root"></div>
11
304
 
12
305
  <script type="module" jsenv-type="module/jsx">
13
306
  import { render } from "preact";
@@ -16,237 +309,321 @@
16
309
  // eslint-disable-next-line no-unused-vars
17
310
  Input,
18
311
  // eslint-disable-next-line no-unused-vars
19
- Field,
312
+ Label,
20
313
  } from "@jsenv/navi";
21
314
 
22
315
  // eslint-disable-next-line no-unused-vars
23
316
  const App = () => {
317
+ return (
318
+ <div className="demo-grid">
319
+ <LoadingDemo />
320
+ <ReadOnlyDemo />
321
+ <DisabledDemo />
322
+ <PropControlDemo />
323
+ </div>
324
+ );
325
+ };
326
+
327
+ // eslint-disable-next-line no-unused-vars
328
+ const LoadingDemo = () => {
24
329
  const [loading, setLoading] = useState(false);
25
- const [loadingB, setLoadingB] = useState(false);
26
- const [loadingC, setLoadingC] = useState(false);
27
- const [loadingD, setLoadingD] = useState(false);
28
- const [loadingE, setLoadingE] = useState(false);
29
- const [loadingF, setLoadingF] = useState(false);
30
330
 
31
331
  return (
32
- <div>
33
- <div style="display: flex; flex-direction: row; gap: 30px">
34
- <div>
35
- <p>
36
- <strong>Loading</strong>
37
- </p>
38
-
39
- <Field
40
- input={
41
- <Input
42
- id="test"
43
- type="checkbox"
44
- name="colors"
45
- loading={loading}
46
- />
47
- }
48
- label="Coucou"
49
- ></Field>
50
-
51
- <button>
52
- <span
53
- onClick={() => {
54
- setLoading(!loading);
55
- }}
56
- >
57
- Toggle
58
- </span>
59
- </button>
60
-
61
- <div>
62
- <label>
63
- <input type="checkbox" name="colors" checked />
64
- Coucou
65
- </label>
66
- </div>
67
- </div>
332
+ <div className="demo-card">
333
+ <h3 className="demo-title">Loading States</h3>
334
+
335
+ <div className="checkbox-row">
336
+ <Label className="checkbox-label">
337
+ <Input type="checkbox" name="loading-demo" loading={loading} />
338
+ Loading Checkbox
339
+ </Label>
340
+ <button
341
+ className="toggle-button"
342
+ onClick={() => setLoading(!loading)}
343
+ >
344
+ {loading ? "Stop Loading" : "Start Loading"}
345
+ </button>
68
346
  </div>
69
347
 
70
- <div>
71
- <div>
72
- <p>
73
- <strong>Loading with action</strong>
74
- </p>
75
-
76
- <Field
77
- input={
78
- <Input
79
- id="test"
80
- action={() => {}}
81
- type="checkbox"
82
- name="colors"
83
- loading={loadingB}
84
- />
85
- }
86
- label="Coucou"
87
- ></Field>
88
-
89
- <button>
90
- <span
91
- onClick={() => {
92
- setLoadingB(!loadingB);
93
- }}
94
- >
95
- Toggle
96
- </span>
97
- </button>
348
+ <div className="comparison">
349
+ <span className="comparison-label">Native comparison:</span>
350
+ <div className="native-examples">
351
+ <label>
352
+ <input type="checkbox" name="native-loading" />
353
+ Standard Checkbox
354
+ </label>
98
355
  </div>
99
356
  </div>
357
+ </div>
358
+ );
359
+ };
100
360
 
101
- <div>
102
- <div>
103
- <p>
104
- <strong>Read Only</strong>
105
- </p>
106
-
107
- <Field
108
- input={
109
- <Input
110
- id="test"
111
- readOnly
112
- type="checkbox"
113
- name="colors"
114
- loading={loadingC}
115
- />
116
- }
117
- label="C"
361
+ // eslint-disable-next-line no-unused-vars
362
+ const ReadOnlyDemo = () => {
363
+ const [loadingUnchecked, setLoadingUnchecked] = useState(false);
364
+ const [loadingChecked, setLoadingChecked] = useState(false);
365
+
366
+ return (
367
+ <div className="demo-card">
368
+ <h3 className="demo-title">Read-Only States</h3>
369
+
370
+ <div className="checkbox-row">
371
+ <Label className="checkbox-label">
372
+ <Input
373
+ type="checkbox"
374
+ name="readonly-unchecked"
375
+ readOnly
376
+ loading={loadingUnchecked}
118
377
  />
378
+ Read-only (Unchecked)
379
+ </Label>
380
+ <button
381
+ className="toggle-button"
382
+ onClick={() => setLoadingUnchecked(!loadingUnchecked)}
383
+ >
384
+ Toggle Loading
385
+ </button>
386
+ </div>
119
387
 
120
- <button>
121
- <span
122
- onClick={() => {
123
- setLoadingC(!loadingC);
124
- }}
125
- >
126
- Toggle
127
- </span>
128
- </button>
129
-
130
- <div>
131
- <label>
132
- <input type="checkbox" name="colors" readonly />C
133
- </label>
134
- </div>
388
+ <div className="checkbox-row">
389
+ <Label className="checkbox-label">
390
+ <Input
391
+ type="checkbox"
392
+ name="readonly-checked"
393
+ readOnly
394
+ checked
395
+ loading={loadingChecked}
396
+ />
397
+ Read-only (Checked)
398
+ </Label>
399
+ <button
400
+ className="toggle-button"
401
+ onClick={() => setLoadingChecked(!loadingChecked)}
402
+ >
403
+ Toggle Loading
404
+ </button>
405
+ </div>
406
+
407
+ <div className="comparison">
408
+ <span className="comparison-label">Native comparison:</span>
409
+ <div className="native-examples">
410
+ <label>
411
+ <input type="checkbox" readOnly />
412
+ Native Read-only (Unchecked)
413
+ </label>
414
+ <label>
415
+ <input type="checkbox" readOnly checked />
416
+ Native Read-only (Checked)
417
+ </label>
135
418
  </div>
136
419
  </div>
420
+ </div>
421
+ );
422
+ };
137
423
 
138
- <div>
139
- <div>
140
- <p>
141
- <strong>Read Only + checked</strong>
142
- </p>
143
-
144
- <Field
145
- input={
146
- <Input
147
- id="test"
148
- readOnly
149
- checked
150
- type="checkbox"
151
- name="colors"
152
- loading={loadingD}
153
- />
154
- }
155
- label="D"
424
+ // eslint-disable-next-line no-unused-vars
425
+ const DisabledDemo = () => {
426
+ const [loadingUnchecked, setLoadingUnchecked] = useState(false);
427
+ const [loadingChecked, setLoadingChecked] = useState(false);
428
+
429
+ return (
430
+ <div className="demo-card">
431
+ <h3 className="demo-title">Disabled States</h3>
432
+
433
+ <div className="checkbox-row">
434
+ <Label className="checkbox-label">
435
+ <Input
436
+ type="checkbox"
437
+ name="disabled-unchecked"
438
+ disabled
439
+ loading={loadingUnchecked}
156
440
  />
441
+ Disabled (Unchecked)
442
+ </Label>
443
+ <button
444
+ className="toggle-button"
445
+ onClick={() => setLoadingUnchecked(!loadingUnchecked)}
446
+ >
447
+ Toggle Loading
448
+ </button>
449
+ </div>
157
450
 
158
- <button>
159
- <span
160
- onClick={() => {
161
- setLoadingD(!loadingD);
162
- }}
163
- >
164
- Toggle
165
- </span>
166
- </button>
167
-
168
- <div>
169
- <label>
170
- <input type="checkbox" name="colors" readonly />D
171
- </label>
172
- </div>
451
+ <div className="checkbox-row">
452
+ <Label className="checkbox-label">
453
+ <Input
454
+ type="checkbox"
455
+ name="disabled-checked"
456
+ disabled
457
+ checked
458
+ loading={loadingChecked}
459
+ />
460
+ Disabled (Checked)
461
+ </Label>
462
+ <button
463
+ className="toggle-button"
464
+ onClick={() => setLoadingChecked(!loadingChecked)}
465
+ >
466
+ Toggle Loading
467
+ </button>
468
+ </div>
469
+
470
+ <div className="comparison">
471
+ <span className="comparison-label">Native comparison:</span>
472
+ <div className="native-examples">
473
+ <label>
474
+ <input type="checkbox" disabled />
475
+ Native Disabled (Unchecked)
476
+ </label>
477
+ <label>
478
+ <input type="checkbox" disabled checked />
479
+ Native Disabled (Checked)
480
+ </label>
173
481
  </div>
174
482
  </div>
483
+ </div>
484
+ );
485
+ };
175
486
 
176
- <div>
177
- <div>
178
- <p>
179
- <strong>Disabled</strong>
180
- </p>
181
-
182
- <Field
183
- input={
184
- <Input
185
- id="test"
186
- disabled
187
- type="checkbox"
188
- name="colors"
189
- loading={loadingE}
190
- />
191
- }
192
- label="E"
193
- />
487
+ // eslint-disable-next-line no-unused-vars
488
+ const PropControlDemo = () => {
489
+ const [accentColor, setAccentColor] = useState(undefined);
490
+ const [isChecked, setIsChecked] = useState(true);
491
+ const [isDisabled, setIsDisabled] = useState(false);
492
+ const [isReadOnly, setIsReadOnly] = useState(false);
493
+ const [isLoading, setIsLoading] = useState(false);
194
494
 
195
- <button>
196
- <span
197
- onClick={() => {
198
- setLoadingE(!loadingE);
199
- }}
200
- >
201
- Toggle
202
- </span>
203
- </button>
204
-
205
- <div>
206
- <label>
207
- <input type="checkbox" name="colors" disabled />E
208
- </label>
209
- </div>
495
+ const colorOptions = [
496
+ { name: "Default (blue)", value: undefined },
497
+ { name: "Orange", value: "#ff8c00" },
498
+ { name: "Green", value: "#28a745" },
499
+ { name: "Purple", value: "#6f42c1" },
500
+ { name: "Red", value: "#dc3545" },
501
+ { name: "Pink", value: "#e83e8c" },
502
+ { name: "Teal", value: "#20c997" },
503
+ ];
504
+
505
+ return (
506
+ <div className="demo-card prop-control-demo">
507
+ <h3 className="demo-title">Interactive Prop Controller</h3>
508
+
509
+ <div className="color-controls">
510
+ <div className="color-select-group">
511
+ <label className="color-select-label">Accent Color:</label>
512
+ <select
513
+ value={accentColor}
514
+ onChange={(e) => setAccentColor(e.target.value)}
515
+ className="color-select"
516
+ >
517
+ {colorOptions.map(({ name, value }) => (
518
+ <option key={value} value={value}>
519
+ {name}
520
+ </option>
521
+ ))}
522
+ </select>
210
523
  </div>
211
524
  </div>
212
525
 
213
- <div>
214
- <div>
215
- <p>
216
- <strong>Disabled + checked</strong>
217
- </p>
218
-
219
- <Field
220
- input={
221
- <Input
222
- id="test"
223
- disabled
224
- checked
225
- type="checkbox"
226
- name="colors"
227
- loading={loadingF}
228
- />
229
- }
230
- label="Coucou"
231
- />
526
+ <div className="state-controls">
527
+ <h4>Checkbox Properties:</h4>
528
+ <div className="control-row">
529
+ <div className="control-group">
530
+ <button
531
+ className={`control-toggle ${isChecked ? "active" : ""}`}
532
+ onClick={() => setIsChecked(!isChecked)}
533
+ >
534
+ {isChecked ? "Checked" : "Unchecked"}
535
+ </button>
536
+ <span className="control-label">checked</span>
537
+ </div>
538
+
539
+ <div className="control-group">
540
+ <button
541
+ className={`control-toggle ${isDisabled ? "active" : ""}`}
542
+ onClick={() => setIsDisabled(!isDisabled)}
543
+ >
544
+ {isDisabled ? "true" : "false"}
545
+ </button>
546
+ <span className="control-label">disabled</span>
547
+ </div>
548
+
549
+ <div className="control-group">
550
+ <button
551
+ className={`control-toggle ${isReadOnly ? "active" : ""}`}
552
+ onClick={() => setIsReadOnly(!isReadOnly)}
553
+ >
554
+ {isReadOnly ? "true" : "false"}
555
+ </button>
556
+ <span className="control-label">readOnly</span>
557
+ </div>
232
558
 
233
- <button>
234
- <span
235
- onClick={() => {
236
- setLoadingF(!loadingF);
237
- }}
559
+ <div className="control-group">
560
+ <button
561
+ className={`control-toggle ${isLoading ? "active" : ""}`}
562
+ onClick={() => setIsLoading(!isLoading)}
238
563
  >
239
- Toggle
240
- </span>
241
- </button>
242
-
243
- <div>
244
- <label>
245
- <input type="checkbox" name="colors" disabled checked />F
246
- </label>
564
+ {isLoading ? "true" : "false"}
565
+ </button>
566
+ <span className="control-label">loading</span>
247
567
  </div>
248
568
  </div>
249
569
  </div>
570
+
571
+ <div className="accent-checkbox-grid">
572
+ <div className="accent-checkbox-item">
573
+ <Label className="checkbox-label">
574
+ <Input
575
+ type="checkbox"
576
+ name="accent-test-checkbox"
577
+ checked={isChecked}
578
+ onUIStateChange={(v) => setIsChecked(Boolean(v))}
579
+ disabled={isDisabled}
580
+ readOnly={isReadOnly}
581
+ loading={isLoading}
582
+ accentColor={accentColor}
583
+ />
584
+ Test Checkbox
585
+ </Label>
586
+ </div>
587
+
588
+ <div className="accent-checkbox-item">
589
+ <Label className="checkbox-label">
590
+ <input
591
+ type="checkbox"
592
+ checked={isChecked}
593
+ onChange={(e) => setIsChecked(e.target.checked)}
594
+ disabled={isDisabled}
595
+ readOnly={isReadOnly}
596
+ style={{ accentColor }}
597
+ />
598
+ Native Comparison
599
+ </Label>
600
+ </div>
601
+ </div>
602
+
603
+ <div
604
+ style={{
605
+ marginTop: "20px",
606
+ padding: "15px",
607
+ background: "rgba(255,255,255,0.1)",
608
+ borderRadius: "8px",
609
+ }}
610
+ >
611
+ <strong>Current Configuration:</strong>
612
+ <br />
613
+ <small>
614
+ checked: {isChecked ? "true" : "false"} | disabled:{" "}
615
+ {isDisabled ? "true" : "false"} | readOnly:{" "}
616
+ {isReadOnly ? "true" : "false"} | loading:{" "}
617
+ {isLoading ? "true" : "false"} | accentColor: {accentColor}
618
+ </small>
619
+ <br />
620
+ <br />
621
+ <small>
622
+ Use the toggle buttons above to test different property
623
+ combinations. Compare how the custom Input component behaves
624
+ versus a native checkbox.
625
+ </small>
626
+ </div>
250
627
  </div>
251
628
  );
252
629
  };