@motifx-community/ui 0.1.0-beta.1 → 0.1.0-beta.3

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.

Potentially problematic release.


This version of @motifx-community/ui might be problematic. Click here for more details.

Files changed (259) hide show
  1. package/CHANGELOG.md +147 -8
  2. package/README.md +19 -13
  3. package/dist/components/accordion/Accordion.d.ts +3 -3
  4. package/dist/components/accordion/AccordionItem.d.ts +1 -1
  5. package/dist/components/calendar/Calendar.d.ts +12 -0
  6. package/dist/components/calendar/calendar-props.d.ts +5 -0
  7. package/dist/components/card/Card.d.ts +1 -1
  8. package/dist/components/contextmenu/ContextMenu.d.ts +1 -1
  9. package/dist/components/datagrid/DataGrid.d.ts +5 -5
  10. package/dist/components/datagrid/data-grid-props.d.ts +2 -2
  11. package/dist/components/datagrid/grid-adaptive-row-expanded-event-args.d.ts +1 -1
  12. package/dist/components/datagrid/grid-adaptive-row-expanding-event-args.d.ts +1 -1
  13. package/dist/components/datagrid/grid-grouping-changed-event-args.d.ts +1 -1
  14. package/dist/components/datagrid/grid-grouping-changing-event-args.d.ts +2 -2
  15. package/dist/components/datagrid/grid-master-detail.d.ts +1 -1
  16. package/dist/components/datagrid/grid-row-expanded-event-args.d.ts +1 -1
  17. package/dist/components/datagrid/grid-row-expanding-event-args.d.ts +1 -1
  18. package/dist/components/datagrid/grid-search-text-changed-event-args.d.ts +1 -1
  19. package/dist/components/datagrid/grid-search-text-changing-event-args.d.ts +1 -1
  20. package/dist/components/datagrid/grid-sort-changing-event-args.d.ts +1 -1
  21. package/dist/components/datagrid/model/GridSearch.d.ts +1 -1
  22. package/dist/components/daterangebox/DateRangeBox.d.ts +121 -0
  23. package/dist/components/daterangebox/date-range-box-props.d.ts +35 -0
  24. package/dist/components/daterangebox/date-range-preset.d.ts +6 -0
  25. package/dist/components/daterangebox/date-range.d.ts +2 -0
  26. package/dist/components/daterangebox/index.d.ts +4 -0
  27. package/dist/components/draggable/Draggable.d.ts +99 -0
  28. package/dist/components/draggable/DropTarget.d.ts +38 -0
  29. package/dist/components/draggable/draggable-event-args.d.ts +17 -0
  30. package/dist/components/draggable/draggable-props.d.ts +37 -0
  31. package/dist/components/draggable/drop-event-args.d.ts +11 -0
  32. package/dist/components/draggable/drop-target-props.d.ts +13 -0
  33. package/dist/components/draggable/index.d.ts +6 -0
  34. package/dist/components/fileuploader/FileUploader.d.ts +133 -0
  35. package/dist/components/fileuploader/file-uploader-props.d.ts +46 -0
  36. package/dist/components/fileuploader/files-added-event-args.d.ts +9 -0
  37. package/dist/components/fileuploader/index.d.ts +7 -0
  38. package/dist/components/fileuploader/upload-event-args.d.ts +10 -0
  39. package/dist/components/fileuploader/upload-item.d.ts +12 -0
  40. package/dist/components/fileuploader/upload-mode.d.ts +2 -0
  41. package/dist/components/fileuploader/upload-status.d.ts +2 -0
  42. package/dist/components/filterbuilder/FilterBuilder.d.ts +1 -1
  43. package/dist/components/gallery/Gallery.d.ts +132 -0
  44. package/dist/components/gallery/gallery-item-click-event-args.d.ts +9 -0
  45. package/dist/components/gallery/gallery-item.d.ts +18 -0
  46. package/dist/components/gallery/gallery-props.d.ts +38 -0
  47. package/dist/components/gallery/index.d.ts +6 -0
  48. package/dist/components/gallery/slide-changed-event-args.d.ts +11 -0
  49. package/dist/components/gallery/slide-changing-event-args.d.ts +14 -0
  50. package/dist/components/layout/ChildSettings.d.ts +1 -1
  51. package/dist/components/layout/DockPanel.d.ts +2 -2
  52. package/dist/components/layout/Grid.d.ts +1 -1
  53. package/dist/components/layout/SplitContainer.d.ts +1 -1
  54. package/dist/components/layout/Stack.d.ts +1 -1
  55. package/dist/components/loadpanel/LoadPanel.d.ts +70 -0
  56. package/dist/components/loadpanel/index.d.ts +3 -0
  57. package/dist/components/loadpanel/load-panel-props.d.ts +29 -0
  58. package/dist/components/loadpanel/load-panel-target.d.ts +3 -0
  59. package/dist/components/multiview/MultiView.d.ts +87 -0
  60. package/dist/components/multiview/View.d.ts +41 -0
  61. package/dist/components/multiview/index.d.ts +6 -0
  62. package/dist/components/multiview/multi-view-props.d.ts +24 -0
  63. package/dist/components/multiview/view-props.d.ts +15 -0
  64. package/dist/components/multiview/view-selecting-event-args.d.ts +15 -0
  65. package/dist/components/multiview/view-selection-changed-event-args.d.ts +12 -0
  66. package/dist/components/numberbox/number-box-props.d.ts +1 -1
  67. package/dist/components/popover/Popover.d.ts +98 -0
  68. package/dist/components/popover/index.d.ts +5 -0
  69. package/dist/components/popover/popover-close-reason.d.ts +2 -0
  70. package/dist/components/popover/popover-closing-event-args.d.ts +8 -0
  71. package/dist/components/popover/popover-props.d.ts +39 -0
  72. package/dist/components/popover/popover-show-on.d.ts +2 -0
  73. package/dist/components/resizable/Resizable.d.ts +84 -0
  74. package/dist/components/resizable/index.d.ts +3 -0
  75. package/dist/components/resizable/resizable-props.d.ts +41 -0
  76. package/dist/components/resizable/resize-event-args.d.ts +13 -0
  77. package/dist/components/scheduler/AppointmentEditor.d.ts +1 -1
  78. package/dist/components/scheduler/scheduler-props.d.ts +1 -1
  79. package/dist/components/scrollview/ScrollView.d.ts +109 -0
  80. package/dist/components/scrollview/index.d.ts +7 -0
  81. package/dist/components/scrollview/pull-down-event-args.d.ts +9 -0
  82. package/dist/components/scrollview/reach-bottom-event-args.d.ts +9 -0
  83. package/dist/components/scrollview/scroll-event-args.d.ts +7 -0
  84. package/dist/components/scrollview/scroll-view-bars.d.ts +2 -0
  85. package/dist/components/scrollview/scroll-view-direction.d.ts +2 -0
  86. package/dist/components/scrollview/scroll-view-props.d.ts +31 -0
  87. package/dist/components/skeleton/Skeleton.d.ts +1 -1
  88. package/dist/components/sortable/Sortable.d.ts +106 -0
  89. package/dist/components/sortable/index.d.ts +5 -0
  90. package/dist/components/sortable/sortable-drag-event-args.d.ts +15 -0
  91. package/dist/components/sortable/sortable-drop-event-args.d.ts +11 -0
  92. package/dist/components/sortable/sortable-orientation.d.ts +2 -0
  93. package/dist/components/sortable/sortable-props.d.ts +34 -0
  94. package/dist/components/speeddial/SpeedDial.d.ts +129 -0
  95. package/dist/components/speeddial/index.d.ts +6 -0
  96. package/dist/components/speeddial/speed-dial-action-click-event-args.d.ts +9 -0
  97. package/dist/components/speeddial/speed-dial-action.d.ts +25 -0
  98. package/dist/components/speeddial/speed-dial-event-args.d.ts +8 -0
  99. package/dist/components/speeddial/speed-dial-props.d.ts +49 -0
  100. package/dist/components/speeddial/speed-dial-tooltip.d.ts +3 -0
  101. package/dist/components/splitter/SplitPane.d.ts +45 -0
  102. package/dist/components/splitter/Splitter.d.ts +116 -0
  103. package/dist/components/splitter/index.d.ts +6 -0
  104. package/dist/components/splitter/split-pane-props.d.ts +21 -0
  105. package/dist/components/splitter/splitter-collapse-event-args.d.ts +13 -0
  106. package/dist/components/splitter/splitter-props.d.ts +25 -0
  107. package/dist/components/splitter/splitter-resize-event-args.d.ts +10 -0
  108. package/dist/components/stepper/Stepper.d.ts +121 -0
  109. package/dist/components/stepper/Wizard.d.ts +112 -0
  110. package/dist/components/stepper/WizardStep.d.ts +44 -0
  111. package/dist/components/stepper/index.d.ts +13 -0
  112. package/dist/components/stepper/step-changed-event-args.d.ts +11 -0
  113. package/dist/components/stepper/step-changing-event-args.d.ts +18 -0
  114. package/dist/components/stepper/stepper-item.d.ts +20 -0
  115. package/dist/components/stepper/stepper-label-position.d.ts +2 -0
  116. package/dist/components/stepper/stepper-orientation.d.ts +1 -0
  117. package/dist/components/stepper/stepper-props.d.ts +32 -0
  118. package/dist/components/stepper/stepper-status.d.ts +2 -0
  119. package/dist/components/stepper/wizard-finishing-event-args.d.ts +7 -0
  120. package/dist/components/stepper/wizard-props.d.ts +48 -0
  121. package/dist/components/stepper/wizard-step-props.d.ts +32 -0
  122. package/dist/components/tabdocs/TabDocumentManager.d.ts +1 -1
  123. package/dist/components/tabs/Tabs.d.ts +2 -2
  124. package/dist/components/tileview/TileView.d.ts +128 -0
  125. package/dist/components/tileview/index.d.ts +6 -0
  126. package/dist/components/tileview/tile-click-event-args.d.ts +9 -0
  127. package/dist/components/tileview/tile-reorder-event-args.d.ts +11 -0
  128. package/dist/components/tileview/tile-selection-changed-event-args.d.ts +11 -0
  129. package/dist/components/tileview/tile-view-item.d.ts +18 -0
  130. package/dist/components/tileview/tile-view-props.d.ts +38 -0
  131. package/dist/components/timeline/Timeline.d.ts +113 -0
  132. package/dist/components/timeline/index.d.ts +5 -0
  133. package/dist/components/timeline/timeline-item-click-event-args.d.ts +9 -0
  134. package/dist/components/timeline/timeline-item.d.ts +24 -0
  135. package/dist/components/timeline/timeline-props.d.ts +30 -0
  136. package/dist/components/timeline/timeline-selection-changed-event-args.d.ts +11 -0
  137. package/dist/components/tooltip/Tooltip.d.ts +1 -1
  138. package/dist/components/treeview/TreeView.d.ts +1 -1
  139. package/dist/components/validationsummary/ValidationSummary.d.ts +56 -0
  140. package/dist/components/validationsummary/index.d.ts +3 -0
  141. package/dist/components/validationsummary/summary-item-click-event-args.d.ts +11 -0
  142. package/dist/components/validationsummary/validation-summary-props.d.ts +17 -0
  143. package/dist/core/control.d.ts +4 -4
  144. package/dist/core/flow-home.d.ts +6 -0
  145. package/dist/core/fold-text.d.ts +6 -0
  146. package/dist/core/ui-locale.d.ts +0 -2
  147. package/dist/core/ui-strings.d.ts +67 -0
  148. package/dist/generated/tokens.d.ts +7270 -4490
  149. package/dist/index.d.ts +17 -1
  150. package/dist/index.js +27131 -20490
  151. package/dist/index.js.map +1 -1
  152. package/dist/locales/en.json +59 -1
  153. package/dist/locales/tr.json +59 -1
  154. package/dist/parts/slide/slide-track-host.d.ts +19 -0
  155. package/dist/parts/slide/slide-track.d.ts +45 -0
  156. package/dist/styles.css +4916 -206
  157. package/dist/tokens/index.d.ts +7270 -4490
  158. package/dist/tokens/index.js +7270 -4490
  159. package/dist/tokens/index.js.map +1 -1
  160. package/dist/tr-C5IXRzAH.js +1233 -0
  161. package/dist/tr-C5IXRzAH.js.map +1 -0
  162. package/docs/accordion.md +9 -9
  163. package/docs/actionsheet.md +2 -2
  164. package/docs/avatar.md +5 -5
  165. package/docs/badge.md +6 -6
  166. package/docs/bottomsheet.md +6 -6
  167. package/docs/breadcrumb.md +4 -4
  168. package/docs/button.md +10 -10
  169. package/docs/buttongroup.md +5 -5
  170. package/docs/calendar.md +6 -6
  171. package/docs/card.md +6 -6
  172. package/docs/checkbox.md +9 -9
  173. package/docs/chip.md +5 -5
  174. package/docs/colorbox.md +3 -3
  175. package/docs/combobox.md +7 -7
  176. package/docs/control.md +12 -12
  177. package/docs/datagrid-api.md +7 -7
  178. package/docs/datagrid-bands.md +1 -1
  179. package/docs/datagrid-drag-select.md +2 -2
  180. package/docs/datagrid-drag.md +1 -1
  181. package/docs/datagrid-editing.md +2 -2
  182. package/docs/datagrid-filtering.md +3 -3
  183. package/docs/datagrid-forms.md +1 -1
  184. package/docs/datagrid-grouping.md +1 -1
  185. package/docs/datagrid-layout.md +4 -4
  186. package/docs/datagrid-lookups.md +1 -1
  187. package/docs/datagrid-master-detail.md +3 -3
  188. package/docs/datagrid-scrolling.md +1 -1
  189. package/docs/datagrid-selection.md +3 -3
  190. package/docs/datagrid.md +8 -8
  191. package/docs/datebox.md +8 -8
  192. package/docs/daterangebox.md +192 -0
  193. package/docs/draggable.md +194 -0
  194. package/docs/drawer.md +1 -1
  195. package/docs/dropdown.md +10 -10
  196. package/docs/fileuploader.md +201 -0
  197. package/docs/filterbuilder.md +9 -9
  198. package/docs/formlayout.md +1 -1
  199. package/docs/gallery.md +244 -0
  200. package/docs/home.md +11 -7
  201. package/docs/keyboard.md +1 -1
  202. package/docs/language.md +229 -0
  203. package/docs/layout.md +15 -15
  204. package/docs/listbox.md +10 -10
  205. package/docs/loadpanel.md +184 -0
  206. package/docs/lookup.md +1 -1
  207. package/docs/menus.md +2 -2
  208. package/docs/multiview.md +202 -0
  209. package/docs/numberbox.md +9 -9
  210. package/docs/pagination.md +4 -4
  211. package/docs/popover.md +221 -0
  212. package/docs/progress.md +9 -9
  213. package/docs/radiogroup.md +7 -7
  214. package/docs/rating.md +4 -4
  215. package/docs/resizable.md +139 -0
  216. package/docs/scheduler-agenda.md +1 -1
  217. package/docs/scheduler-big-data.md +1 -1
  218. package/docs/scheduler-editing.md +5 -5
  219. package/docs/scheduler-form.md +1 -1
  220. package/docs/scheduler-icalendar.md +1 -1
  221. package/docs/scheduler-mobile.md +1 -1
  222. package/docs/scheduler-recurrence.md +2 -2
  223. package/docs/scheduler-resources.md +1 -1
  224. package/docs/scheduler-timeline.md +1 -1
  225. package/docs/scheduler.md +4 -4
  226. package/docs/scrollview.md +185 -0
  227. package/docs/showcase.md +1 -1
  228. package/docs/skeleton.md +2 -2
  229. package/docs/slider.md +9 -9
  230. package/docs/sortable.md +213 -0
  231. package/docs/speeddial.md +290 -0
  232. package/docs/splitter.md +204 -0
  233. package/docs/stepper.md +238 -0
  234. package/docs/switch.md +7 -7
  235. package/docs/tabdocs-dock.md +3 -3
  236. package/docs/tabdocs-drag.md +1 -1
  237. package/docs/tabdocs-menus.md +1 -1
  238. package/docs/tabdocs-mobile.md +1 -1
  239. package/docs/tabdocs-tabs.md +1 -1
  240. package/docs/tabdocs-windows.md +1 -1
  241. package/docs/tabdocs-workspace.md +1 -1
  242. package/docs/tabdocs.md +5 -5
  243. package/docs/tabs.md +11 -11
  244. package/docs/tagbox.md +10 -10
  245. package/docs/textarea.md +9 -9
  246. package/docs/textbox.md +10 -10
  247. package/docs/tileview.md +206 -0
  248. package/docs/timeline.md +174 -0
  249. package/docs/toast.md +7 -7
  250. package/docs/tokens.md +678 -122
  251. package/docs/toolbar.md +8 -8
  252. package/docs/tooltip.md +12 -12
  253. package/docs/treeview.md +11 -11
  254. package/docs/validationsummary.md +115 -0
  255. package/docs/window.md +7 -7
  256. package/docs/wizard.md +240 -0
  257. package/llms-full.txt +4813 -492
  258. package/llms.txt +21 -3
  259. package/package.json +9 -3
@@ -0,0 +1,192 @@
1
+ # DateRangeBox
2
+
3
+ > Editors · @motifx-community/ui 0.1.0-beta.3
4
+
5
+ A start and an end date in one field: typed through two masks, or picked on two months side by side, from ready-made ranges, within the dates and the span allowed. The value is a `[start, end]` pair.
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { DateRangeBox, type DateRange } from '@motifx-community/ui';
11
+ ```
12
+
13
+ ## Declarative and programmatic
14
+
15
+ ```tsx
16
+ import { reactive } from '@motifx/core';
17
+ import { Button, DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
18
+
19
+ const say = (d: Date | null) => (d ? d.toLocaleDateString('en-GB') : '—');
20
+
21
+ /** A range bound with x-model, and one made programmatically and read through its properties. */
22
+ export default function Programmatic() {
23
+ const s = reactive({ stay: [new Date(2026, 2, 10), new Date(2026, 2, 14)] as DateRange, told: '' });
24
+ const coded = new DateRangeBox({ label: 'Report period', clearButton: true, onValueChanged: e => (s.told = `${say(e.value[0])} to ${say(e.value[1])}`) });
25
+
26
+ return (
27
+ <Stack gap="md">
28
+ <Stack orientation="horizontal" wrap align="center">
29
+ <DateRangeBox label="Stay" x-model={() => s.stay} clearButton />
30
+ <output class="dr-stay">{() => `${say(s.stay[0])} to ${say(s.stay[1])}`}</output>
31
+ </Stack>
32
+ <Stack orientation="horizontal" wrap align="center">
33
+ <span onConfig={c => c.controls.add(coded)} />
34
+ <Button text="This week" variant="outline" onclick={() => (coded.value = [new Date(2026, 2, 16), new Date(2026, 2, 22)])} />
35
+ <output class="dr-told">{() => s.told}</output>
36
+ </Stack>
37
+ </Stack>
38
+ );
39
+ }
40
+ ```
41
+
42
+ ## Presets
43
+
44
+ `presets` puts ready-made ranges beside the calendars: `true` for the kit’s, or your own, each made when it is chosen. `calendars={1}` shows one month.
45
+
46
+ ```tsx
47
+ import { reactive } from '@motifx/core';
48
+ import { DateRangeBox, Stack, type DateRange, type DateRangePreset } from '@motifx-community/ui';
49
+
50
+ const day = (offset: number) => {
51
+ const d = new Date();
52
+ d.setHours(0, 0, 0, 0);
53
+ d.setDate(d.getDate() + offset);
54
+ return d;
55
+ };
56
+
57
+ // Ranges of our own, made when chosen so they are about today.
58
+ const QUARTERS: DateRangePreset[] = [
59
+ { text: 'Next 3 days', range: () => [day(0), day(2)] },
60
+ { text: 'Next week', range: () => [day(1), day(7)] },
61
+ { text: 'Next 90 days', range: () => [day(0), day(89)] }
62
+ ];
63
+
64
+ /** The kit's presets beside the calendars, and presets of your own. */
65
+ export default function Presets() {
66
+ const s = reactive({ sales: [null, null] as DateRange, plan: [null, null] as DateRange });
67
+ return (
68
+ <Stack orientation="horizontal" wrap align="center">
69
+ <DateRangeBox label="Sales period" presets x-model={() => s.sales} />
70
+ <DateRangeBox label="Planning" presets={QUARTERS} calendars={1} x-model={() => s.plan} />
71
+ </Stack>
72
+ );
73
+ }
74
+ ```
75
+
76
+ ## Limits
77
+
78
+ `min`, `max` and `disabledDates` bound both ends, typed or picked; `minDays` and `maxDays` bound the span, and the calendars offer only the days within while the end is being picked. A failed rule says which.
79
+
80
+ ```tsx
81
+ import { reactive } from '@motifx/core';
82
+ import { Button, DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
83
+
84
+ const today = new Date();
85
+ const inMonths = (n: number) => new Date(today.getFullYear(), today.getMonth() + n, today.getDate());
86
+
87
+ /** A stay of one to fourteen nights, within the next six months, never starting on a Sunday; the message says which rule failed. */
88
+ export default function Limits() {
89
+ const s = reactive({ stay: [null, null] as DateRange, told: '' });
90
+ let box!: DateRangeBox;
91
+ return (
92
+ <Stack orientation="horizontal" wrap align="center">
93
+ <DateRangeBox
94
+ ref={(b: DateRangeBox) => (box = b)}
95
+ label="Stay"
96
+ min={today}
97
+ max={inMonths(6)}
98
+ minDays={1}
99
+ maxDays={14}
100
+ disabledDates={d => d.getDay() === 0}
101
+ required
102
+ x-model={() => s.stay}
103
+ />
104
+ <Button text="Check" variant="outline" onclick={() => void box.validate().then(ok => (s.told = ok ? 'Fine.' : box.validationMessage))} />
105
+ <output class="dr-check">{() => s.told}</output>
106
+ </Stack>
107
+ );
108
+ }
109
+ ```
110
+
111
+ ## With a time, and in another locale
112
+
113
+ ```tsx
114
+ import { reactive } from '@motifx/core';
115
+ import { DateRangeBox, Stack, type DateRange } from '@motifx-community/ui';
116
+
117
+ /** Date and time on both ends: the time is typed after the date, the calendars keep it; one box in Turkish. */
118
+ export default function DateTime() {
119
+ const s = reactive({ shift: [new Date(2026, 2, 10, 8, 30), new Date(2026, 2, 10, 17, 0)] as DateRange, trip: [null, null] as DateRange });
120
+ return (
121
+ <Stack orientation="horizontal" wrap align="center">
122
+ <DateRangeBox label="Shift" type="datetime" x-model={() => s.shift} displayFormat={{ dateStyle: 'short', timeStyle: 'short' }} />
123
+ <DateRangeBox label="Seyahat" locale="tr-TR" showWeekNumbers x-model={() => s.trip} startPlaceholder="gidiş" endPlaceholder="dönüş" />
124
+ </Stack>
125
+ );
126
+ }
127
+ ```
128
+
129
+ ## Behaviour
130
+
131
+ | Topic | How |
132
+ | --- | --- |
133
+ | `Typing` | Each side is a masked input in the locale’s order (`22.11.2006`); a whole, real date is taken as it is finished, an emptied side becomes `null`. Tab moves from the start to the end. |
134
+ | `Picking` | On the popup the first pick is the start, the second the end: an earlier second pick becomes the start. With both chosen, the next pick starts a new range. While the end is being picked, the pointer shows the range it would make. |
135
+ | `Two months` | The calendars show the start’s month and the next; paging one pages the other with it. |
136
+ | `Presets` | A list beside the calendars; a press takes the range and closes. |
137
+ | `Keyboard` | Alt+Down opens the popup; in it the calendars take the arrow keys, Enter picks; Escape closes, and clears the field when `clearButton` is on and the popup is closed. |
138
+
139
+ ## Accessibility
140
+
141
+ | Topic | How |
142
+ | --- | --- |
143
+ | `Inputs` | Two text boxes named “<label>, Start date” and “<label>, End date” in the kit language; the field’s label marks the start. |
144
+ | `Popup` | A dialog named “Choose date”; the calendars are the kit’s grids, the presets a list box. |
145
+ | `Messages` | The rules speak in the kit language; a rule of your own in yours. |
146
+
147
+ ## Styling
148
+
149
+ | Hook | What it is |
150
+ | --- | --- |
151
+ | `.mx-date-range-box` | The field. `data-type`. |
152
+ | `.mx-date-range-box__start, .mx-date-range-box__end, .mx-date-range-box__separator` | The inputs and the glyph between them. |
153
+ | `.mx-date-range-box__toggle, .mx-date-range-box__clear` | The buttons in the box. |
154
+ | `.mx-date-range-box__popup, .mx-date-range-box__calendar, .mx-date-range-box__presets` | The popup, each calendar, the presets. |
155
+
156
+ ### Component tokens
157
+
158
+ | Token | What it sets |
159
+ | --- | --- |
160
+ | `date-range-box.separator, .presets` | Units: the glyph between the inputs (`icon`, `bg`), the list of presets (`focus`, `beside`). |
161
+ | `date-range-box.calendar` | Place: a calendar on the popup. |
162
+ | `date-range-box.popup-gap` | Between the calendars and the presets. |
163
+ | `calendar.cell range-start, range-end, range-single, range-in` | The calendar’s cells in a range: its ends and the days between, drawn by each language. |
164
+
165
+ ## API reference
166
+
167
+ ### Props
168
+
169
+ | Prop | Type | Default | Description |
170
+ | --- | --- | --- | --- |
171
+ | `value` | `Bind<DateRange>` | `[null, null]` | The `[start, end]` pair; either `null` while not chosen. `x-model` binds it two-way. |
172
+ | `type` | `Bind<'date' \| 'datetime'>` | `'date'` | With `datetime` the time is typed after the date; the calendars keep it. |
173
+ | `min, max, disabledDates` | `Bind<Date \| null>`, `Bind<(d: Date) => boolean>` | — | The dates allowed, on both ends, typed or picked. |
174
+ | `minDays, maxDays` | `Bind<number \| null>` | `null` | The least and the most days a range may span, the end counted from the start; while the end is picked the calendars offer only days within. |
175
+ | `presets` | `Bind<readonly DateRangePreset[] \| boolean>` | `false` | `true`: the kit’s ready-made ranges beside the calendars (today, yesterday, the last 7 and 30 days, this and last month); your own as `{ text, range: () => DateRange }`. |
176
+ | `calendars` | `Bind<1 \| 2>` | `2` | Months side by side on the popup; two stay a month apart as one is paged. |
177
+ | `closeOnComplete` | `Bind<boolean>` | `true` | The popup closes once both ends are picked. |
178
+ | `locale, displayFormat, firstDayOfWeek, showWeekNumbers, showSeconds` | | | As on the `DateBox`. |
179
+ | `startPlaceholder, endPlaceholder` | `Bind<string>` | `''` | Shown in an empty box. |
180
+ | `clearButton, showPickerButton` | `Bind<boolean>` | `false`, `true` | The clear button; the button that opens the calendars. |
181
+ | `label, helpText, required, rules, readOnly, size, variant…` | | | The field props, as on every editor. |
182
+
183
+ ### Events, properties and methods
184
+
185
+ | Member | Kind | Description |
186
+ | --- | --- | --- |
187
+ | `startDate, endDate` | `Date \| null` | The ends as properties of their own. |
188
+ | `inputElement, endInputElement` | read-only | The start’s and the end’s inputs. |
189
+ | `open(), close(), opened` | `boolean` / `void` | The popup with the calendars; `onOpened`, `onClosed`. |
190
+ | `clear()` | `void` | Empties both ends. |
191
+ | `validate(), validationMessage, isValid` | | As on every field: an unfinished date, a date outside `min`, `max` or `disabledDates`, a start after the end, a span under `minDays` or over `maxDays`. |
192
+ | `onValueChanged` | event | The pair changed (`value`, `previousValue`, `byUser`). |
@@ -0,0 +1,194 @@
1
+ # Draggable and DropTarget
2
+
3
+ > Navigation · @motifx-community/ui 0.1.0-beta.3
4
+
5
+ Anything the user moves with the pointer, a finger or the arrow keys, along an axis or inside a boundary, by a handle or as a copy; and the targets that take it. For items that change places in a list, see [Sortable](sortable.md).
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { Draggable, DropTarget } from '@motifx-community/ui';
11
+ ```
12
+
13
+ ## Moving things
14
+
15
+ The JSX children are what moves. `boundary` keeps it inside its parent or an element, `axis` keeps it on a line, `handle` names the only part that takes the press and the keys. A drag writes the place to `x-model` and `onDragEnded` tells it; Escape brings it back.
16
+
17
+ ```tsx
18
+ import { reactive } from '@motifx/core';
19
+ import { Draggable, Panel, Stack } from '@motifx-community/ui';
20
+
21
+ /** Three notes in a room: one moves anywhere inside it, one only sideways, one only by its grip; the keys move the focused one. */
22
+ export default function Free() {
23
+ const s = reactive({ told: '' });
24
+ const note = (text: string, grip = false) => (
25
+ <Panel padding="sm" variant="outline" style="inline-size: 150px">
26
+ {grip && <span class="dg-grip">⋮⋮ </span>}
27
+ <span>{text}</span>
28
+ </Panel>
29
+ );
30
+ return (
31
+ <Stack gap="sm" style="inline-size: 100%">
32
+ <div class="dg-room" style="position: relative; block-size: 220px; outline: 2px dashed var(--mx-color-stroke-control-strong); outline-offset: -2px">
33
+ <Draggable class="dg-free" boundary="parent" style="position: absolute; left: 16px; top: 16px" onDragEnded={e => (s.told = `free: ${e.x}, ${e.y}`)}>
34
+ {note('Anywhere in the room')}
35
+ </Draggable>
36
+ <Draggable class="dg-axis" axis="x" boundary="parent" style="position: absolute; left: 16px; top: 100px" onDragEnded={e => (s.told = `sideways: ${e.x}, ${e.y}`)}>
37
+ {note('Only sideways')}
38
+ </Draggable>
39
+ <Draggable class="dg-handle" handle=".dg-grip" boundary="parent" style="position: absolute; left: 300px; top: 16px" onDragEnded={e => (s.told = `by the grip: ${e.x}, ${e.y}`)}>
40
+ {note('Only by the grip', true)}
41
+ </Draggable>
42
+ </div>
43
+ <output class="dg-free-told">{() => s.told}</output>
44
+ </Stack>
45
+ );
46
+ }
47
+ ```
48
+
49
+ ## Drop targets
50
+
51
+ A `DropTarget` of the same `group` takes a draggable dropped on it and is told in `onDropped` with the draggable’s `data`; `onDragEntering` may refuse. With `clone` a copy follows the pointer and the draggable stays, so one thing can be dropped many times. What a drop does to your data is yours.
52
+
53
+ ```tsx
54
+ import { reactive } from '@motifx/core';
55
+ import { Draggable, DropTarget, Stack } from '@motifx-community/ui';
56
+
57
+ const FRUIT = ['Apple', 'Pear', 'Plum'];
58
+
59
+ /** Copies of the chips go to the bowls of their group; the small bowl refuses a third, and the data moves in `onDropped`. */
60
+ export default function Targets() {
61
+ const s = reactive({ big: [] as string[], small: [] as string[], told: '' });
62
+ const bowl = (name: 'big' | 'small', limit: number) => (
63
+ <DropTarget
64
+ class={`dg-bowl dg-bowl-${name}`}
65
+ group="fruit"
66
+ grow
67
+ style="flex-basis: 0; min-block-size: 96px; padding: 12px; border: 1px solid var(--mx-color-stroke-divider); border-radius: var(--mx-radius-md)"
68
+ onDragEntering={e => (e.cancel = s[name].length >= limit)}
69
+ onDropped={e => {
70
+ s[name].push(e.data as string);
71
+ s.told = `${e.data} went to the ${name} bowl`;
72
+ }}
73
+ >
74
+ <strong>{name === 'big' ? 'Big bowl' : 'Small bowl, two at most'}</strong>
75
+ <div class="dg-bowl-list">{() => s[name].join(', ') || 'empty'}</div>
76
+ </DropTarget>
77
+ );
78
+ return (
79
+ <Stack gap="md" style="inline-size: 100%">
80
+ <Stack orientation="horizontal" gap="sm" wrap>
81
+ {FRUIT.map(fruit => (
82
+ <Draggable class="dg-chip" clone group="fruit" data={fruit} style="padding: 6px 12px; border-radius: var(--mx-radius-full); border: 1px solid var(--mx-color-stroke-control-strong)">
83
+ {fruit}
84
+ </Draggable>
85
+ ))}
86
+ </Stack>
87
+ <Stack orientation="horizontal" gap="md">
88
+ {bowl('big', 99)}
89
+ {bowl('small', 2)}
90
+ </Stack>
91
+ <output class="dg-bowls-told">{() => s.told}</output>
92
+ </Stack>
93
+ );
94
+ }
95
+ ```
96
+
97
+ ## Programmatic use
98
+
99
+ `position` puts it where you say, in pixels from where it was laid out, and `x-model` takes the place back after every drag or key: kept and restored.
100
+
101
+ ```tsx
102
+ import { reactive } from '@motifx/core';
103
+ import { Button, Draggable, Panel, Stack } from '@motifx-community/ui';
104
+
105
+ /** The place goes out to x-model after every drag or key and comes back: moved, kept and restored programmatically. */
106
+ export default function Programmatic() {
107
+ const s = reactive({ at: { x: 0, y: 0 } as { x: number; y: number } | null, kept: null as { x: number; y: number } | null });
108
+ return (
109
+ <Stack gap="sm" style="inline-size: 100%">
110
+ <div style="position: relative; block-size: 160px">
111
+ <Draggable class="dg-coded" boundary="parent" step={20} x-model={() => s.at} style="position: absolute; left: 0; top: 0">
112
+ <Panel padding="sm" variant="outline" style="inline-size: 140px">
113
+ Moved by the model
114
+ </Panel>
115
+ </Draggable>
116
+ </div>
117
+ <Stack orientation="horizontal" wrap align="center">
118
+ <Button text="Right by 40" variant="outline" onclick={() => (s.at = { x: (s.at?.x ?? 0) + 40, y: s.at?.y ?? 0 })} />
119
+ <Button text="Keep this place" variant="outline" onclick={() => (s.kept = s.at ? { ...s.at } : null)} />
120
+ <Button text="Restore it" variant="outline" enabled={() => !!s.kept} onclick={() => (s.at = s.kept ? { ...s.kept } : null)} />
121
+ <Button text="Back to the start" variant="outline" onclick={() => (s.at = { x: 0, y: 0 })} />
122
+ <output class="dg-coded-told">{() => `at: ${JSON.stringify(s.at)}`}</output>
123
+ </Stack>
124
+ </Stack>
125
+ );
126
+ }
127
+ ```
128
+
129
+ ## Keyboard
130
+
131
+ | Key | What it does |
132
+ | --- | --- |
133
+ | `Tab` | The draggable (or its handle) is one stop. |
134
+ | `Arrow keys` | Move it by `step` pixels along its axis, inside its boundary; the new place is read out. |
135
+ | `Escape` | While dragging: lets go and brings it back where it started. |
136
+
137
+ ## Accessibility
138
+
139
+ | Topic | How |
140
+ | --- | --- |
141
+ | `The draggable` | A `group` with `aria-roledescription="draggable"` named “Move” in the kit language; with a `handle`, that element is a button of that name instead. |
142
+ | `Dragging` | A long press lifts it on a touch screen. While it is dragged it lets the pointer through, so the target under it is found; the copy of a `clone` follows the pointer. |
143
+ | `Targets` | Marked while a drag of their group is under way, while the draggable is over them, and when they refuse it. |
144
+
145
+ ## Styling
146
+
147
+ | Hook | What it is |
148
+ | --- | --- |
149
+ | `.mx-draggable` | The draggable. `data-dragging`, `data-handle`, `data-clone`, `data-axis`. |
150
+ | `.mx-draggable__handle, .mx-draggable__ghost` | The handle named by `handle`; the copy after the pointer. |
151
+ | `.mx-drop-target` | A target. `data-drop-active` during a drag of its group, `data-drop-over`, `data-drop-refused`. |
152
+
153
+ ### Component tokens
154
+
155
+ | Token | What it sets |
156
+ | --- | --- |
157
+ | `draggable.box, .handle, .ghost` | Units: the draggable (`draggable`, `dragging`, `focus`), its handle (`hover`, `focus`), the copy. |
158
+ | `drop-target.target` | Unit: a target (`active`, `over`, `refused`). |
159
+
160
+ ## API reference
161
+
162
+ ### Draggable props
163
+
164
+ | Prop | Type | Default | Description |
165
+ | --- | --- | --- | --- |
166
+ | `axis` | `Bind<DragAxis>` | `'both'` | `both`, `x` or `y`. |
167
+ | `boundary` | `Bind<'parent' \| HTMLElement \| null>` | `null` | The draggable stays inside this: its parent, or an element it lies in. |
168
+ | `handle` | `Bind<string \| null>` | `null` | A selector inside the draggable: only a press there drags it, and it takes the Tab stop and the keys. |
169
+ | `clone` | `Bind<boolean>` | `false` | A copy follows the pointer and the draggable stays where it is; for a drop target to take. |
170
+ | `group` | `Bind<string \| null>` | `null` | Drop targets of the same group take it. |
171
+ | `data` | `unknown` | — | Anything of your own, given to the drop target with the drop. |
172
+ | `step` | `Bind<number>` | `10` | Pixels an arrow key moves it by. |
173
+ | `position` | `Bind<DragPosition \| null>` | `null` | Where it stands, in pixels from where it was laid out: given, it is applied; after every drag or key the new place is written to `x-model`. |
174
+
175
+ ### DropTarget props and events
176
+
177
+ | Prop | Type | Default | Description |
178
+ | --- | --- | --- | --- |
179
+ | `group` | `Bind<string \| null>` | `null` | Takes the draggables of this group; `null` takes those without one. |
180
+ | `onDragEntering` | event | A draggable came over it (`draggable`, `data`); `cancel = true` refuses it. |
181
+ | `onDragLeaving` | event | The draggable left it. |
182
+ | `onDropped` | event | A draggable was dropped on it: your data is yours to move. |
183
+
184
+ ### Events, properties and methods
185
+
186
+ | Member | Kind | Description |
187
+ | --- | --- | --- |
188
+ | `onDragStarting` | event | A drag is about to begin; `cancel = true` keeps it in place. |
189
+ | `onDragging` | event | It is being dragged (`x`, `y`, the `target` under the pointer). |
190
+ | `onDragEnding` | event | The pointer let go; `cancel = true` brings it back where it started. |
191
+ | `onDragEnded` | event | The drag ended (`x`, `y`, `target`, `dropped`). |
192
+ | `currentPosition` | read-only | Where it stands now. |
193
+ | `isDragging` | read-only | A drag is under way. |
194
+ | `handleElement` | read-only | What takes the press and the keys: the handle, else the draggable itself. |
package/docs/drawer.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Drawer
2
2
 
3
- > Navigation · @motifx-community/ui 0.1.0-beta.1
3
+ > Navigation · @motifx-community/ui 0.1.0-beta.3
4
4
 
5
5
  A panel that slides in from an edge of the page or of a container, over the content or pushing it aside. A finger swipes it in from the edge and back again; Escape, the scrim and the browser's back close it.
6
6
 
package/docs/dropdown.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DropDown
2
2
 
3
- > Choice · @motifx-community/ui 0.1.0-beta.1
3
+ > Choice · @motifx-community/ui 0.1.0-beta.3
4
4
 
5
5
  Picks one item from a list. The field shows the chosen item; the list opens below it with the keyboard or a press, can be searched, grouped and drawn your way, and stays fast with thousands of items.
6
6
 
@@ -10,9 +10,9 @@ Picks one item from a list. The field shows the chosen item; the list opens belo
10
10
  import { DropDown, type DropDownItem } from '@motifx-community/ui';
11
11
  ```
12
12
 
13
- ## From JSX and from code
13
+ ## Declarative and programmatic
14
14
 
15
- `items` can be plain values; `x-model` binds the value. Created with `new`, the same properties are set from code.
15
+ `items` can be plain values; `x-model` binds the value. Created with `new`, the same properties are set programmatically.
16
16
 
17
17
  ```tsx
18
18
  /** The cities the drop-downs of the examples show. */
@@ -156,14 +156,14 @@ The search box, the clear button, the empty list text, the wait (`loading`) and
156
156
 
157
157
  ```tsx
158
158
  import { reactive } from '@motifx/core';
159
- import { Button, DropDown, enStrings, trStrings, uiLocale } from '@motifx-community/ui';
159
+ import { Button, DropDown, uiLocale } from '@motifx-community/ui';
160
160
 
161
161
  /** Switches the texts of every drop-down on the page: the search box, the clear button, the empty list. */
162
162
  export default function Localization() {
163
163
  const s = reactive({ lang: 'en' });
164
164
  const toggle = () => {
165
165
  s.lang = s.lang === 'en' ? 'tr' : 'en';
166
- uiLocale.strings = s.lang === 'en' ? enStrings : trStrings;
166
+ void uiLocale.use(s.lang);
167
167
  };
168
168
  return (
169
169
  <>
@@ -249,20 +249,20 @@ The list is a shared part, `OptionList`, exported for combo boxes, list boxes an
249
249
 
250
250
  ## Example files
251
251
 
252
- `FromCode.tsx`
252
+ `Programmatic.tsx`
253
253
 
254
254
  ```tsx
255
255
  import { reactive } from '@motifx/core';
256
256
  import { Button, DropDown, Stack } from '@motifx-community/ui';
257
257
  import { cities } from './cities';
258
258
 
259
- /** Drop-downs bound with x-model, and drop-downs created with `new` and added from code. */
260
- export default function FromCode() {
259
+ /** Drop-downs bound with x-model, and drop-downs created with `new` and added programmatically. */
260
+ export default function Programmatic() {
261
261
  const form = reactive({ city: 'İzmir' as string | null, size: null as string | null, result: '' });
262
262
  let added = 0;
263
263
  let host: Stack | null = null;
264
264
 
265
- const addFromCode = () => {
265
+ const addProgrammatic = () => {
266
266
  const size = new DropDown<string, string>({ label: `Size ${++added}`, items: ['S', 'M', 'L'], placeholder: 'Pick one' });
267
267
  size.onValueChanged((e) => (form.result = `${size.label}: ${e.value}`));
268
268
  host?.controls.add(size);
@@ -277,7 +277,7 @@ export default function FromCode() {
277
277
  </Stack>
278
278
  <DropDown label="Size" items={['S', 'M', 'L', 'XL']} placeholder="Pick one" x-model={() => form.size} clearButton />
279
279
  <Stack orientation="horizontal" wrap align="center">
280
- <Button text="Add a drop-down from code" variant="outline" onclick={addFromCode} />
280
+ <Button text="Add a drop-down programmatically" variant="outline" onclick={addProgrammatic} />
281
281
  <output class="dd-made">{() => form.result}</output>
282
282
  </Stack>
283
283
  <Stack orientation="horizontal" wrap align="center" ref={(c: Stack) => (host = c)} />
@@ -0,0 +1,201 @@
1
+ # FileUploader
2
+
3
+ > Editors · @motifx-community/ui 0.1.0-beta.3
4
+
5
+ Files chosen with a button or dropped on the box, listed with their size and what happens to them: uploaded as they come, on a button or programmatically, with progress, cancel, retry and remove on each. Files outside the limits are listed with the reason.
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { FileUploader } from '@motifx-community/ui';
11
+ ```
12
+
13
+ ## Choosing, dropping, uploading
14
+
15
+ `upload` is your own way to send a file: report progress, stop on the signal, resolve to the response. With `uploadUrl` instead, the uploader sends the file itself, in one piece or in chunks (`chunkSize`).
16
+
17
+ ```tsx
18
+ import { reactive } from '@motifx/core';
19
+ import { FileUploader, Stack } from '@motifx-community/ui';
20
+
21
+ // Stands in for a server: takes two seconds per megabyte, reports as it goes, stops on the signal.
22
+ const send = (file: File, report: (fraction: number) => void, signal: AbortSignal) =>
23
+ new Promise<string>((resolve, reject) => {
24
+ const steps = 20;
25
+ const wait = Math.max(600, Math.min(4000, (file.size / 1_000_000) * 2000)) / steps;
26
+ let step = 0;
27
+ const timer = setInterval(() => {
28
+ step++;
29
+ report(step / steps);
30
+ if (step === steps) {
31
+ clearInterval(timer);
32
+ resolve(`id-${file.name}`);
33
+ }
34
+ }, wait);
35
+ signal.addEventListener('abort', () => {
36
+ clearInterval(timer);
37
+ reject(new Error('stopped'));
38
+ });
39
+ });
40
+
41
+ /** Files chosen or dropped go up as they come, through your own upload; each row shows progress, cancel, retry, remove. */
42
+ export default function Basic() {
43
+ const s = reactive({ files: [] as readonly File[], told: '' });
44
+ return (
45
+ <Stack gap="md" style="inline-size: 100%">
46
+ <FileUploader
47
+ label="Attachments"
48
+ helpText="Any files; a stand-in server takes them."
49
+ upload={send}
50
+ x-model={() => s.files}
51
+ onUploaded={e => (s.told = `${e.file.name} is up as ${String(e.item.response)}.`)}
52
+ onUploadAborted={e => (s.told = `${e.file.name} was stopped.`)}
53
+ />
54
+ <output class="fu-told">{() => s.told || `${s.files.length} file(s) taken`}</output>
55
+ </Stack>
56
+ );
57
+ }
58
+ ```
59
+
60
+ ## Limits
61
+
62
+ ```tsx
63
+ import { reactive } from '@motifx/core';
64
+ import { FileUploader, Stack } from '@motifx-community/ui';
65
+
66
+ /** Only pictures and PDFs, up to 2 MB each and three in all; a file outside is listed with the reason. */
67
+ export default function Limits() {
68
+ const s = reactive({ files: [] as readonly File[], refused: '' });
69
+ return (
70
+ <Stack gap="md" style="inline-size: 100%">
71
+ <FileUploader
72
+ label="Documents"
73
+ accept=".pdf,image/*"
74
+ maxFileSize={2_000_000}
75
+ maxFiles={3}
76
+ required
77
+ x-model={() => s.files}
78
+ onFilesAdded={e => (s.refused = e.refused.length ? e.refused.map(r => r.message).join(' ') : '')}
79
+ />
80
+ <output class="fu-refused">{() => s.refused}</output>
81
+ </Stack>
82
+ );
83
+ }
84
+ ```
85
+
86
+ ## When files go up
87
+
88
+ ```tsx
89
+ import { reactive } from '@motifx/core';
90
+ import { Button, FileUploader, Stack } from '@motifx-community/ui';
91
+
92
+ const quick = (file: File, report: (fraction: number) => void) =>
93
+ new Promise<void>(resolve => {
94
+ let step = 0;
95
+ const timer = setInterval(() => {
96
+ report(++step / 10);
97
+ if (step === 10) {
98
+ clearInterval(timer);
99
+ resolve();
100
+ }
101
+ }, 120);
102
+ });
103
+
104
+ /** An Upload button sends what was chosen; or nothing goes until code says so. One file only, no dropping. */
105
+ export default function Modes() {
106
+ const s = reactive({ one: [] as readonly File[] });
107
+ let manual!: FileUploader;
108
+ return (
109
+ <Stack gap="md" style="inline-size: 100%">
110
+ <FileUploader label="Photo" multiple={false} allowDrop={false} accept="image/*" upload={quick} uploadMode="button" x-model={() => s.one} />
111
+ <Stack orientation="horizontal" wrap align="center">
112
+ <FileUploader ref={(u: FileUploader) => (manual = u)} label="Logs" accept=".log,.txt" upload={quick} uploadMode="manual" />
113
+ <Button text="Send the logs" variant="outline" onclick={() => void manual.upload()} />
114
+ </Stack>
115
+ </Stack>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ## Sending to a server
121
+
122
+ The uploader posts a form with the file in `uploadField` (`file` by default) to `uploadUrl`, with `uploadHeaders`; a 2xx answer is the item’s `response`, JSON parsed when it is JSON. With `chunkSize` each piece carries `Content-Range` and the fields `chunkIndex` and `chunkCount`.
123
+
124
+ ```tsx
125
+ <FileUploader
126
+ label="Attachments"
127
+ uploadUrl="/api/files"
128
+ uploadHeaders={{ Authorization: 'Bearer ' + token }}
129
+ chunkSize={1_000_000}
130
+ onUploaded={(e) => this.attachments.push(e.item.response as Attachment)}
131
+ />
132
+ ```
133
+
134
+ ## Behaviour
135
+
136
+ | Topic | How |
137
+ | --- | --- |
138
+ | `Choosing` | The button opens the file dialog; files may be dropped on the box too, which lights up while they are over it. |
139
+ | `Refusing` | A file outside `accept`, the sizes or `maxFiles` is listed as refused with the reason, and is not in the value. |
140
+ | `Uploading` | As chosen, on the Upload button, or programmatically. A row shows the progress and a Cancel button meanwhile; afterwards “Uploaded”, or the failure with Retry. The server’s answer is the item’s `response` (JSON parsed). |
141
+ | `Chunks` | With `chunkSize` the file goes in pieces, each a request with `Content-Range: bytes start-end/total`; progress runs over the whole. |
142
+ | `Removing` | Each row has a remove button; a running upload is stopped first. |
143
+
144
+ ## Accessibility
145
+
146
+ | Topic | How |
147
+ | --- | --- |
148
+ | `Button` | The select button is the field’s control: the label marks it, Space and Enter open the dialog. |
149
+ | `List` | A list of rows: the name, the size and the state as text; the progress bar named after the file; the buttons named “Cancel the upload of …”, “Retry”, “Remove …”. |
150
+ | `Messages` | The reasons a file was refused and the failures speak in the kit language, or in the server’s words. |
151
+
152
+ ## Styling
153
+
154
+ | Hook | What it is |
155
+ | --- | --- |
156
+ | `.mx-file-uploader` | The field. `data-dragover` while files are over it. |
157
+ | `.mx-file-uploader__select, .mx-file-uploader__drop, .mx-file-uploader__upload` | The select button, the hint, the Upload button. |
158
+ | `.mx-file-uploader__list, .mx-file-uploader__item` | The list and each row. `data-status` on the row. |
159
+ | `.mx-file-uploader__icon, __name, __size, __state, __progress, __actions, __action` | The parts of a row. |
160
+
161
+ ### Component tokens
162
+
163
+ | Token | What it sets |
164
+ | --- | --- |
165
+ | `file-uploader.over, .select, .upload, .hint, .list, .item, .icon, .name, .size, .state` | Units: the box with files over it, the two buttons (`hover`, `pressed`, `focus`, `disabled`), the hint, the list, a row per status, the file glyph, the texts. |
166
+ | `file-uploader.field, .action` | Places: the field’s box as a drop zone (a dashed frame, its corners, its padding); the row’s buttons. |
167
+ | `file-uploader.box-gap, .button-gap, .item-gap` | The spaces in the box, in a button and in a row. |
168
+
169
+ ## API reference
170
+
171
+ ### Props
172
+
173
+ | Prop | Type | Default | Description |
174
+ | --- | --- | --- | --- |
175
+ | `value` | `Bind<readonly File[]>` | `[]` | The files taken (the refused ones are not in it). `x-model` binds it two-way. |
176
+ | `multiple` | `Bind<boolean>` | `true` | Several files at once; `false` keeps one, the newest. |
177
+ | `accept` | `Bind<string>` | `''` | What may be chosen, as for `<input type="file">`: `.png,.jpg`, `image/*`, `application/pdf`. |
178
+ | `maxFileSize, minFileSize` | `Bind<number \| null>` | `null` | Bytes. A file outside is listed as refused, with the reason. |
179
+ | `maxFiles` | `Bind<number \| null>` | `null` | How many files may be taken in all. |
180
+ | `allowDrop` | `Bind<boolean>` | `true` | Files may be dropped on the box. |
181
+ | `uploadMode` | `Bind<UploadMode>` | `instant` / `manual` | `instant`: as chosen; `button`: an Upload button; `manual`: `upload()` programmatically. Default `instant` with `uploadUrl` or `upload`, else `manual`. |
182
+ | `uploadUrl, uploadMethod, uploadHeaders, uploadField` | `Bind<string \| null>`, … | `null`, `POST`, `null`, `file` | Where and how the uploader itself sends a file (XMLHttpRequest, with progress), as a form with the file in `uploadField`. |
183
+ | `chunkSize` | `Bind<number \| null>` | `null` | Bytes per request: the file goes in pieces, each with its `Content-Range` and `chunkIndex` / `chunkCount` fields; the last answer is the response. |
184
+ | `upload` | `(file, report, signal) => Promise<unknown>` | — | Your own upload instead of `uploadUrl`: call `report(0…1)` as it goes, stop on `signal`; what it resolves to is the response. |
185
+ | `selectText, dropText, uploadText` | `Bind<string>` | the kit’s | The button, the hint beside it, the Upload button. |
186
+ | `showFileList` | `Bind<boolean>` | `true` | The list of files under the box. |
187
+ | `label, helpText, required, rules, readOnly, size, variant…` | | | The field props, as on every editor. |
188
+
189
+ ### Events, properties and methods
190
+
191
+ | Member | Kind | Description |
192
+ | --- | --- | --- |
193
+ | `items` | read-only | Every file in the list with what happened to it: `file`, `status` (`ready`, `uploading`, `done`, `error`, `aborted`, `invalid`), `progress`, `response`, `message`. |
194
+ | `isUploading` | read-only | An upload is running. |
195
+ | `openDialog()` | `void` | Opens the browser’s file dialog, as the button does. |
196
+ | `addFiles(files)` | `void` | Takes files as if chosen: the limits apply, `onFilesAdded` is asked, uploads start as the mode says. |
197
+ | `upload(item?)` | `Promise<void>` | Uploads the files waiting, or one of them; what `manual` mode calls. |
198
+ | `abort(item?), remove(item), clear()` | `void` | Stops an upload (the file stays, cancelled); takes a file out; takes every file out. |
199
+ | `onFilesAdded` | event | Files were chosen or dropped (`files`, `refused`); `cancel = true` takes none. |
200
+ | `onFileRemoved, onUploadStarted, onProgress, onUploaded, onUploadError, onUploadAborted` | event | One file’s way through: each with `item` and `file`, a failure with `error`. |
201
+ | `onValueChanged` | event | The files taken changed. |