@cahyo-dimas/freeday 1.53.0 → 2.0.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.
Files changed (145) hide show
  1. package/CHANGELOG.md +657 -535
  2. package/COMPONENTS.md +153 -135
  3. package/README.id.md +46 -45
  4. package/README.md +46 -43
  5. package/USAGE.md +39 -35
  6. package/adapters/blazor/FdyAppShell.razor +50 -0
  7. package/adapters/blazor/FdyAppShell.razor.cs +114 -0
  8. package/adapters/blazor/FdyCfl.razor.cs +1 -1
  9. package/adapters/blazor/FdyChart.razor +1 -1
  10. package/adapters/blazor/FdyChart.razor.cs +3 -3
  11. package/adapters/blazor/FdyChartSeries.cs +1 -1
  12. package/adapters/blazor/FdyCombo.razor.cs +2 -2
  13. package/adapters/blazor/FdyModal.razor +1 -1
  14. package/adapters/blazor/FdyTable.razor.cs +7 -7
  15. package/adapters/blazor/FdyTableFilter.razor +1 -1
  16. package/adapters/blazor/FdyTableFooter.razor +1 -1
  17. package/adapters/blazor/FdyTableFooter.razor.cs +4 -4
  18. package/adapters/blazor/Freeday.Blazor.csproj +1 -1
  19. package/adapters/blazor/FreedayComponentBase.cs +1 -1
  20. package/adapters/blazor/TableModel.cs +3 -3
  21. package/adapters/blazor/TableTypes.cs +3 -3
  22. package/adapters/blazor/freeday-blazor.js +5 -5
  23. package/adapters/core/app-shell.d.ts +30 -0
  24. package/adapters/core/app-shell.js +134 -0
  25. package/adapters/core/table-model.d.ts +2 -2
  26. package/adapters/core/table-model.js +8 -8
  27. package/adapters/react/components/FdyAppShell.tsx +159 -0
  28. package/adapters/react/components/FdyAutocomplete.tsx +1 -1
  29. package/adapters/react/components/FdyCascade.tsx +1 -1
  30. package/adapters/react/components/FdyCfl.tsx +11 -11
  31. package/adapters/react/components/FdyDateRange.tsx +2 -2
  32. package/adapters/react/components/FdyDatepicker.tsx +5 -5
  33. package/adapters/react/components/FdyDrawer.tsx +1 -1
  34. package/adapters/react/components/FdyModal.tsx +2 -2
  35. package/adapters/react/components/FdyTable.tsx +7 -7
  36. package/adapters/react/components/FdyTableFilter.tsx +1 -1
  37. package/adapters/react/components/FdyTableFooter.tsx +5 -5
  38. package/adapters/react/index.d.ts +2 -1
  39. package/adapters/react/index.js +1 -0
  40. package/adapters/react/useFreeday.js +3 -3
  41. package/adapters/vue/components/FdyAppShell.vue +160 -0
  42. package/adapters/vue/components/FdyAutocomplete.vue +1 -1
  43. package/adapters/vue/components/FdyCascade.vue +1 -1
  44. package/adapters/vue/components/FdyCfl.vue +8 -8
  45. package/adapters/vue/components/FdyChart.vue +2 -2
  46. package/adapters/vue/components/FdyCombo.vue +1 -1
  47. package/adapters/vue/components/FdyDateRange.vue +2 -2
  48. package/adapters/vue/components/FdyDatepicker.vue +5 -5
  49. package/adapters/vue/components/FdyDrawer.vue +3 -3
  50. package/adapters/vue/components/FdyModal.vue +3 -3
  51. package/adapters/vue/components/FdyTable.vue +7 -7
  52. package/adapters/vue/components/FdyTableFilter.vue +1 -1
  53. package/adapters/vue/components/FdyTableFooter.vue +5 -5
  54. package/adapters/vue/index.d.ts +3 -2
  55. package/adapters/vue/index.js +1 -0
  56. package/adapters/vue/useFreeday.js +3 -3
  57. package/dist/asset.d.ts +3 -3
  58. package/dist/freeday-app-shell.js +49 -9
  59. package/dist/freeday-autocomplete.js +2 -2
  60. package/dist/freeday-breakpoint.js +1 -1
  61. package/dist/freeday-carousel.js +5 -5
  62. package/dist/freeday-cascade.js +7 -7
  63. package/dist/freeday-cfl.js +9 -9
  64. package/dist/freeday-chart.js +11 -11
  65. package/dist/freeday-chip.js +3 -3
  66. package/dist/freeday-datepicker.js +11 -7
  67. package/dist/freeday-datetime.js +5 -5
  68. package/dist/freeday-drawer.js +1 -1
  69. package/dist/freeday-form.js +14 -14
  70. package/dist/freeday-mask.js +6 -6
  71. package/dist/freeday-menu.js +1 -1
  72. package/dist/freeday-number.js +3 -3
  73. package/dist/freeday-popover.js +3 -3
  74. package/dist/freeday-rating.js +2 -2
  75. package/dist/freeday-select.js +5 -5
  76. package/dist/freeday-slider.js +2 -2
  77. package/dist/freeday-stepper.js +7 -7
  78. package/dist/freeday-table.js +15 -15
  79. package/dist/freeday-tabs.js +1 -1
  80. package/dist/freeday-timepicker.js +2 -2
  81. package/dist/freeday-toast.js +8 -8
  82. package/dist/freeday-tree.js +3 -3
  83. package/dist/freeday-upload.js +25 -25
  84. package/dist/freeday.bundle.css +176 -176
  85. package/dist/freeday.css +170 -170
  86. package/dist/freeday.d.ts +2 -2
  87. package/dist/freeday.js +202 -158
  88. package/dist/freeday.tokens.css +5 -5
  89. package/docs/agent-onboarding.md +42 -42
  90. package/docs/getting-started.md +35 -35
  91. package/docs/integrations.md +18 -18
  92. package/docs/reference-screen.html +14 -14
  93. package/package.json +5 -4
  94. package/src/base.css +6 -6
  95. package/src/components/accordion.css +4 -4
  96. package/src/components/alert.css +1 -1
  97. package/src/components/app-shell.css +10 -10
  98. package/src/components/appbar.css +3 -3
  99. package/src/components/autocomplete.css +1 -1
  100. package/src/components/avatar.css +3 -3
  101. package/src/components/badge.css +5 -5
  102. package/src/components/breadcrumb.css +1 -1
  103. package/src/components/breakpoints.css +4 -4
  104. package/src/components/button.css +13 -13
  105. package/src/components/card.css +8 -8
  106. package/src/components/carousel.css +2 -2
  107. package/src/components/cascade.css +2 -2
  108. package/src/components/cfl.css +4 -4
  109. package/src/components/chart.css +3 -3
  110. package/src/components/chip.css +2 -2
  111. package/src/components/combo.css +3 -3
  112. package/src/components/composition.css +7 -7
  113. package/src/components/datepicker.css +6 -6
  114. package/src/components/datetimepicker.css +1 -1
  115. package/src/components/description-list.css +1 -1
  116. package/src/components/divider.css +1 -1
  117. package/src/components/drawer.css +1 -1
  118. package/src/components/file-upload.css +5 -5
  119. package/src/components/filterbar.css +7 -7
  120. package/src/components/form-grid.css +2 -2
  121. package/src/components/input-group.css +6 -6
  122. package/src/components/input.css +6 -6
  123. package/src/components/kbd.css +1 -1
  124. package/src/components/list.css +6 -6
  125. package/src/components/menu.css +3 -3
  126. package/src/components/modal.css +1 -1
  127. package/src/components/pagination.css +1 -1
  128. package/src/components/progress.css +1 -1
  129. package/src/components/rating.css +2 -2
  130. package/src/components/selection.css +4 -4
  131. package/src/components/skeleton.css +1 -1
  132. package/src/components/slider.css +1 -1
  133. package/src/components/spinner.css +1 -1
  134. package/src/components/states.css +1 -1
  135. package/src/components/stepper.css +2 -2
  136. package/src/components/table.css +15 -15
  137. package/src/components/tabs.css +3 -3
  138. package/src/components/timeline.css +1 -1
  139. package/src/components/timepicker.css +1 -1
  140. package/src/components/toast.css +3 -3
  141. package/src/components/tooltip.css +1 -1
  142. package/src/components/tree.css +2 -2
  143. package/tokens/breakpoints.d.ts +2 -2
  144. package/tokens/breakpoints.mjs +3 -3
  145. package/tokens/tokens.json +1 -1
@@ -1,4 +1,4 @@
1
- /* Freeday input mask + password reveal enhancer (optional, zero-dependency).
1
+ /* Freeday, input mask + password reveal enhancer (optional, zero-dependency).
2
2
  *
3
3
  * [data-fdy-mask]="pattern" formats a text input as you type. Placeholders:
4
4
  * # a digit (0-9) A a letter (a-z/A-Z) * a letter or digit
@@ -51,16 +51,16 @@
51
51
  }
52
52
 
53
53
 
54
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
55
- * path and every one overridable per element, so a host that speaks another language (the
54
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
55
+ * path, and every one overridable per element, so a host that speaks another language (the
56
56
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
57
57
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
58
58
  var TEXT = {
59
- show: 'Tampilkan kata sandi',
60
- hide: 'Sembunyikan kata sandi'
59
+ show: 'Show password',
60
+ hide: 'Hide password'
61
61
  };
62
62
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
63
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
63
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
64
64
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
65
65
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
66
66
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday menu enhancer (optional, zero-dependency).
1
+ /* Freeday, menu enhancer (optional, zero-dependency).
2
2
  * Menu-button pattern (WAI-ARIA APG): a trigger with aria-haspopup="menu" toggles a
3
3
  * role="menu" popup of role="menuitem" buttons. Also powers the split button
4
4
  * (main action + attached caret toggle). Auto-inits [data-fdy-menu].
@@ -1,7 +1,7 @@
1
- /* Freeday number field enhancer (optional, zero-dependency).
1
+ /* Freeday, number field enhancer (optional, zero-dependency).
2
2
  * Gives a native <input type="number"> its increment/decrement affordance back, on the kit's terms:
3
3
  * .fdy-input hides the user agent's own spin buttons (unthemeable OS widgets), so this puts two real
4
- * buttons in an .fdy-input-group instead. No new block the group already owns the shared border,
4
+ * buttons in an .fdy-input-group instead. No new block, the group already owns the shared border,
5
5
  * :focus-within ring and error promotion.
6
6
  *
7
7
  * Markup contract:
@@ -67,7 +67,7 @@
67
67
  if (frozen()) return;
68
68
  if (Number(btn.getAttribute('data-fdy-number-step')) < 0) input.stepDown();
69
69
  else input.stepUp();
70
- /* The value changed without the user typing, so say so the way the platform does frameworks
70
+ /* The value changed without the user typing, so say so the way the platform does, frameworks
71
71
  listen to these, not to a kit-specific event. */
72
72
  input.dispatchEvent(new Event('input', { bubbles: true }));
73
73
  input.dispatchEvent(new Event('change', { bubbles: true }));
@@ -1,7 +1,7 @@
1
- /* Freeday popover positioning helper (optional, zero-dependency).
1
+ /* Freeday, popover positioning helper (optional, zero-dependency).
2
2
  * Lifts a dropdown panel into the top layer via the native Popover API so it escapes ANY
3
3
  * ancestor overflow clip (a .fdy-card with overflow:hidden, an app-shell main with
4
- * overflow:auto, …), then positions it `fixed` against its trigger flipping above when
4
+ * overflow:auto, …), then positions it `fixed` against its trigger, flipping above when
5
5
  * there is no room below, and matching the trigger width. The panel stays a DOM child of its
6
6
  * component, so focus, outside-click (.closest), and ARIA relationships keep working unchanged.
7
7
  *
@@ -21,7 +21,7 @@
21
21
  && typeof HTMLElement.prototype.showPopover === 'function';
22
22
 
23
23
  // Position `panel` (already shown, so it has a measurable box) against `trigger`'s rect.
24
- // matchWidth (default true) floors the panel to the trigger width right for input-shaped
24
+ // matchWidth (default true) floors the panel to the trigger width, right for input-shaped
25
25
  // dropdowns (combo/cascade/date/time), skipped for menus that keep their own min-width.
26
26
  function place(panel, trigger, matchWidth) {
27
27
  var r = trigger.getBoundingClientRect();
@@ -1,7 +1,7 @@
1
- /* Freeday rating enhancer (optional, zero-dependency).
1
+ /* Freeday, rating enhancer (optional, zero-dependency).
2
2
  * Fills stars up to the checked radio (and previews on hover) for an interactive
3
3
  * [data-fdy-rating] radio group; for [data-fdy-readonly] it fills from data-value.
4
- * The radios are native arrow-key selection and form association come for free.
4
+ * The radios are native, arrow-key selection and form association come for free.
5
5
  */
6
6
  (function () {
7
7
  'use strict';
@@ -1,8 +1,8 @@
1
- /* Freeday combobox enhancer (optional, zero-dependency).
1
+ /* Freeday, combobox enhancer (optional, zero-dependency).
2
2
  * Implements the WAI-ARIA APG "select-only combobox" pattern for every
3
3
  * [data-fdy-combo] on the page. Progressive enhancement: the markup is the
4
4
  * component, this script wires behavior. In a Vue/React/Blazor app you would
5
- * bind your own state instead this is the framework-agnostic reference.
5
+ * bind your own state instead, this is the framework-agnostic reference.
6
6
  *
7
7
  * Expected markup:
8
8
  * <div class="fdy-combo" data-fdy-combo data-value="x">
@@ -25,7 +25,7 @@
25
25
  var seq = 0;
26
26
  var openClose = null; // close() of the currently-open combo, or null
27
27
 
28
- /* The tick lives in CSS now, so the option's text IS its label no sibling walk to skip a glyph. */
28
+ /* The tick lives in CSS now, so the option's text IS its label, no sibling walk to skip a glyph. */
29
29
  function optionLabel(opt) {
30
30
  return (opt.textContent || '').trim();
31
31
  }
@@ -91,7 +91,7 @@
91
91
  if (openClose === close) openClose = null;
92
92
  }
93
93
  // Mark an option selected + reflect it in the button. `silent` skips the change
94
- // event, close, and focus used by the programmatic setValue() below so a host
94
+ // event, close, and focus, used by the programmatic setValue() below so a host
95
95
  // (e.g. a Blazor/framework wrapper) can push a value in without echoing an event
96
96
  // back to itself or stealing focus. User-driven picks go through choose() (loud).
97
97
  function select(opt, silent) {
@@ -126,7 +126,7 @@
126
126
  isOpen() ? close() : open();
127
127
  });
128
128
  // Pressing an option must not blur the button: a blur fires the focusout
129
- // handler below, which closes the listbox before the option's click lands
129
+ // handler below, which closes the listbox before the option's click lands,
130
130
  // so the pick is lost (real mouse only; synthetic .click() never blurs).
131
131
  // preventDefault on mousedown keeps focus on the button without blocking click.
132
132
  listbox.addEventListener('mousedown', function (e) { e.preventDefault(); });
@@ -1,7 +1,7 @@
1
- /* Freeday slider value binding (optional, zero-dependency).
1
+ /* Freeday, slider value binding (optional, zero-dependency).
2
2
  * Mirrors a [data-fdy-slider] range input's value into <output for="inputId">, with an
3
3
  * optional prefix/suffix on the output (data-fdy-prefix / data-fdy-suffix). The range itself
4
- * is a native input keyboard and ARIA are built in; this only updates the visible readout.
4
+ * is a native input, keyboard and ARIA are built in; this only updates the visible readout.
5
5
  */
6
6
  (function () {
7
7
  'use strict';
@@ -1,6 +1,6 @@
1
- /* Freeday stepper/wizard enhancer (optional, zero-dependency).
1
+ /* Freeday, stepper/wizard enhancer (optional, zero-dependency).
2
2
  * Drives a step header + panels: prev/next navigation, completed/active state, and
3
- * clicking a reached step to revisit it (linear can't skip ahead). Auto-inits
3
+ * clicking a reached step to revisit it (linear, can't skip ahead). Auto-inits
4
4
  * [data-fdy-stepper].
5
5
  *
6
6
  * Markup: <div data-fdy-stepper>
@@ -19,16 +19,16 @@
19
19
  var CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg>';
20
20
 
21
21
 
22
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
23
- * path and every one overridable per element, so a host that speaks another language (the
22
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
23
+ * path, and every one overridable per element, so a host that speaks another language (the
24
24
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
25
25
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
26
26
  var TEXT = {
27
- done: 'Selesai',
28
- next: 'Lanjut'
27
+ done: 'Done',
28
+ next: 'Next'
29
29
  };
30
30
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
31
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
31
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
32
32
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
33
33
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
34
34
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday data-table enhancer (optional, zero-dependency).
1
+ /* Freeday, data-table enhancer (optional, zero-dependency).
2
2
  * Adds client-side search, column sort, pagination and row selection to any
3
3
  * [data-fdy-table]. Progressive enhancement over a plain semantic <table>;
4
4
  * in a framework app, do this server- or store-side instead.
@@ -34,26 +34,26 @@
34
34
  }
35
35
 
36
36
 
37
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
38
- * path and every one overridable per element, so a host that speaks another language (the
37
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
38
+ * path, and every one overridable per element, so a host that speaks another language (the
39
39
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
40
40
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
41
41
  var TEXT = {
42
- prev: 'Sebelumnya',
43
- next: 'Berikutnya',
44
- selected: '{n} dipilih',
45
- filter: 'Filter kolom',
46
- filterText: 'Berisi teks',
47
- filterTextPlaceholder: 'Berisi…',
48
- filterEnum: 'Tampilkan nilai',
49
- filterRange: 'Rentang nilai',
42
+ prev: 'Previous',
43
+ next: 'Next',
44
+ selected: '{n} selected',
45
+ filter: 'Filter column',
46
+ filterText: 'Contains text',
47
+ filterTextPlaceholder: 'Contains…',
48
+ filterEnum: 'Show values',
49
+ filterRange: 'Value range',
50
50
  reset: 'Reset',
51
- close: 'Tutup',
52
- rows: '{n} baris',
53
- info: 'Menampilkan {from}–{to} dari {total}'
51
+ close: 'Close',
52
+ rows: '{n} rows',
53
+ info: 'Showing {from}–{to} of {total}'
54
54
  };
55
55
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
56
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
56
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
57
57
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
58
58
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
59
59
  still resolves, for markup written against 1.39.0. */
@@ -1,4 +1,4 @@
1
- /* Freeday tabs enhancer (optional, zero-dependency, WAI-ARIA APG tabs).
1
+ /* Freeday, tabs enhancer (optional, zero-dependency, WAI-ARIA APG tabs).
2
2
  * Auto-inits every [data-fdy-tabs]. Roving tabindex + arrow/Home/End nav.
3
3
  *
4
4
  * Markup: a [data-fdy-tabs] with a [role="tablist"] of
@@ -1,4 +1,4 @@
1
- /* Freeday time picker enhancer (optional, zero-dependency).
1
+ /* Freeday, time picker enhancer (optional, zero-dependency).
2
2
  * Builds an input-styled trigger + scrollable time-list popover (WAI-ARIA listbox)
3
3
  * from an empty [data-fdy-timepicker] wrapper. 24h HH:MM. Options run from
4
4
  * data-min (default 00:00) to data-max (default 23:59) every data-step minutes
@@ -28,7 +28,7 @@
28
28
  wrap.dataset.fdyTpReady = '1';
29
29
  wrap.classList.add('fdy-timepicker');
30
30
 
31
- var label = wrap.getAttribute('data-label') || 'Pilih waktu';
31
+ var label = wrap.getAttribute('data-label') || 'Choose a time';
32
32
  var placeholder = wrap.getAttribute('data-placeholder') || '--:--';
33
33
  var step = Math.max(1, parseInt(wrap.getAttribute('data-step') || '30', 10));
34
34
  var minM = valid(wrap.getAttribute('data-min')) ? toMin(wrap.getAttribute('data-min')) : 0;
@@ -1,9 +1,9 @@
1
- /* Freeday toast API (optional, zero-dependency).
1
+ /* Freeday, toast API (optional, zero-dependency).
2
2
  * Freeday.toast({ variant, title, message, timeout, key }) shows a transient
3
3
  * notification in a live region (created on first use). Returns the element.
4
4
  * variant: 'success' | 'warning' | 'danger' | 'info' (default: neutral)
5
5
  * timeout: ms before auto-dismiss (default 4000; 0 = sticky)
6
- * key: optional stable id a new toast with the same key REPLACES the
6
+ * key: optional stable id, a new toast with the same key REPLACES the
7
7
  * existing one in place instead of stacking a duplicate (e.g. a burst
8
8
  * of identical failures shows one toast, refreshed).
9
9
  * Freeday.dismiss(nodeOrKey) closes a toast early (pass the returned element or its key).
@@ -39,14 +39,14 @@
39
39
 
40
40
  /* Put the region in the TOP LAYER, above any open <dialog>.
41
41
  *
42
- * A modal dialog lives in the top layer, where z-index does not reach so a toast raised by an
42
+ * A modal dialog lives in the top layer, where z-index does not reach, so a toast raised by an
43
43
  * action taken inside a modal was painted behind that modal's backdrop, which is where an error
44
44
  * message is least useful. showPopover() joins the same layer, and membership there is ordered by
45
45
  * when you joined: hide-then-show re-joins at the top, so a toast shown while a dialog is open
46
46
  * lands above it rather than under the dialog that was opened after the last toast.
47
47
  *
48
48
  * Guarded twice on purpose. `showPopover` is absent before Chrome 114 / Safari 17 / Firefox 125,
49
- * and the call throws if the element is disconnected or already open in every one of those
49
+ * and the call throws if the element is disconnected or already open, in every one of those
50
50
  * cases the region stays an ordinary fixed block at z-index 200, which is what it has always
51
51
  * been. A notification must never be the thing that throws.
52
52
  */
@@ -77,15 +77,15 @@
77
77
  }
78
78
 
79
79
 
80
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
81
- * path and every one overridable per element, so a host that speaks another language (the
80
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
81
+ * path, and every one overridable per element, so a host that speaks another language (the
82
82
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
83
83
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
84
84
  var TEXT = {
85
- close: 'Tutup'
85
+ close: 'Close'
86
86
  };
87
87
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
88
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
88
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
89
89
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
90
90
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
91
91
  still resolves, for markup written against 1.39.0. */
@@ -1,7 +1,7 @@
1
- /* Freeday tree checkbox cascade (optional, zero-dependency).
1
+ /* Freeday, tree checkbox cascade (optional, zero-dependency).
2
2
  * Turns a [data-fdy-tree] checkbox tree into a selectable one: checking a branch checks
3
3
  * every descendant; a partially-selected branch shows the native :indeterminate state.
4
- * Rows are native <input class="fdy-checkbox">, labelled via aria-label Space toggles.
4
+ * Rows are native <input class="fdy-checkbox">, labelled via aria-label. Space toggles.
5
5
  * Selection never toggles the <details> (the checkbox stops click propagation).
6
6
  *
7
7
  * Markup contract:
@@ -25,7 +25,7 @@
25
25
  return Array.prototype.filter.call(ul.children, function (n) { return n.tagName === 'LI'; });
26
26
  }
27
27
 
28
- // The checkbox belonging to a row's own <li> branch summary or leaf, never a child's.
28
+ // The checkbox belonging to a row's own <li>, branch summary or leaf, never a child's.
29
29
  function ownBox(li) {
30
30
  return li.querySelector(':scope > details > summary input[type="checkbox"]')
31
31
  || li.querySelector(':scope > input[type="checkbox"]');
@@ -1,13 +1,13 @@
1
- /* Freeday file-upload enhancer (optional, zero-dependency).
1
+ /* Freeday, file-upload enhancer (optional, zero-dependency).
2
2
  * A drop target that also opens the file dialog on click / Enter / Space, validates each file
3
3
  * (accept + max size), and renders a per-file row with explicit state. Actual upload is the
4
- * consumer's job this is a controlled reference: wire the emitted event's row API to your
4
+ * consumer's job, this is a controlled reference: wire the emitted event's row API to your
5
5
  * upload call, or set data-fdy-upload-simulate for a demo progress animation.
6
6
  *
7
7
  * Markup contract:
8
8
  * <div class="fdy-dropzone" data-fdy-dropzone role="button" tabindex="0"
9
9
  * data-max-size="10485760" data-filelist="#dz-list" [data-fdy-upload-simulate]
10
- * aria-label="Unggah berkas seret ke sini atau tekan Enter">
10
+ * aria-label="Unggah berkas, seret ke sini atau tekan Enter">
11
11
  * <span class="fdy-dropzone__icon">…svg…</span>
12
12
  * <span class="fdy-dropzone__title">…</span>
13
13
  * <span class="fdy-dropzone__hint">…</span>
@@ -15,15 +15,15 @@
15
15
  * </div>
16
16
  * <div class="fdy-filelist" id="dz-list"></div>
17
17
  *
18
- * Emits bubbling CustomEvents BOTH on the dropzone element, which is the one target a consumer
18
+ * Emits bubbling CustomEvents. BOTH on the dropzone element, which is the one target a consumer
19
19
  * needs to listen on:
20
20
  * "fdy-upload-add" {file, rejected, reason, row}
21
21
  * "fdy-upload-remove" {file}
22
22
  * `row` is the state machine over the rendered .fdy-file:
23
- * .ready() (rest where a dropped file starts) / .uploading() / .setProgress(pct) /
23
+ * .ready() (rest, where a dropped file starts) / .uploading() / .setProgress(pct) /
24
24
  * .waiting(label) (sent, awaiting the server) / .done() / .fail(msg) / .el
25
25
  * Note the file list is a SIBLING of the dropzone above, so nothing dispatched on a row would ever
26
- * bubble through the zone which is why removal fires on the zone and not on the row.
26
+ * bubble through the zone, which is why removal fires on the zone and not on the row.
27
27
  */
28
28
  (function () {
29
29
  'use strict';
@@ -51,21 +51,21 @@
51
51
  }
52
52
 
53
53
 
54
- /* User-facing strings. Indonesian by default documented and deliberate for the raw enhancer
55
- * path and every one overridable per element, so a host that speaks another language (the
54
+ /* User-facing strings. Indonesian by default, documented and deliberate for the raw enhancer
55
+ * path, and every one overridable per element, so a host that speaks another language (the
56
56
  * Blazor adapters, an English app on the raw path) supplies its own without forking this file.
57
57
  * Keeping them in ONE table is also what lets a guard prove none is hard-coded further down. */
58
58
  var TEXT = {
59
- remove: 'Hapus {name}',
60
- progress: 'Progres unggah {name}',
61
- uploading: 'Mengunggah…',
62
- waiting: 'Menunggu server…',
63
- done: 'Terunggah',
64
- badType: 'Tipe berkas tidak didukung.',
65
- tooBig: 'Ukuran melebihi batas ({max}).'
59
+ remove: 'Remove {name}',
60
+ progress: 'Upload progress for {name}',
61
+ uploading: 'Uploading…',
62
+ waiting: 'Waiting for the server…',
63
+ done: 'Uploaded',
64
+ badType: 'Unsupported file type.',
65
+ tooBig: 'Over the {max} limit.'
66
66
  };
67
67
  /* HTML lowercases attribute names, so a camelCase key like `filterText` can only ever be written
68
- as `data-fdy-text-filtertext` while the kebab form anybody would reach for,
68
+ as `data-fdy-text-filtertext`, while the kebab form anybody would reach for,
69
69
  `data-fdy-text-filter-text`, becomes a DIFFERENT attribute the enhancer never reads, and the
70
70
  override fails silently. So the key is kebab-cased for the lookup; the run-together spelling
71
71
  still resolves, for markup written against 1.39.0. */
@@ -103,12 +103,12 @@
103
103
  remove.setAttribute('aria-label', textOf(zone, 'remove', { name: file.name }));
104
104
  remove.innerHTML = '&times;';
105
105
  remove.addEventListener('click', function () {
106
- /* Dispatched on the ZONE, not on the row the same target as fdy-upload-add, so one listener
106
+ /* Dispatched on the ZONE, not on the row, the same target as fdy-upload-add, so one listener
107
107
  on the dropzone gets both. The row lives in the file list, which the kit's own markup
108
108
  contract puts as a SIBLING of the dropzone, so a row event never bubbles through the zone:
109
109
  a consumer following the docs saw `add` arrive and `remove` never fire, with no error.
110
- Firing on both would look safer, but it makes the pair asymmetric one `add` and, for
111
- anyone delegating on a common ancestor, two `remove`s which is its own silent bug. It
110
+ Firing on both would look safer, but it makes the pair asymmetric, one `add` and, for
111
+ anyone delegating on a common ancestor, two `remove`s, which is its own silent bug. It
112
112
  also fixes the listless case: a row that was never attached bubbles to nothing at all. */
113
113
  zone.dispatchEvent(new CustomEvent('fdy-upload-remove', { bubbles: true, detail: { file: file } }));
114
114
  el.remove();
@@ -140,14 +140,14 @@
140
140
  }
141
141
  /* Back to a measured bar. While the indeterminate modifier is on it owns the bar's width, so an
142
142
  explicit one has to be restored when it comes off: .fdy-progress__bar is a plain block div, and
143
- with no width at all it fills the track a full bar, which is the opposite of what 0% means. */
143
+ with no width at all it fills the track, a full bar, which is the opposite of what 0% means. */
144
144
  function determinate() {
145
145
  progressEl.classList.remove('fdy-progress--indeterminate');
146
146
  if (!bar.style.width) bar.style.width = '0%';
147
147
  }
148
148
  return {
149
149
  el: el,
150
- /* The state a row starts in: chosen, not yet sent. The size alone it makes no claim about
150
+ /* The state a row starts in: chosen, not yet sent. The size alone, it makes no claim about
151
151
  a transfer, and no progress bar is shown, because nothing is in flight. Without this the
152
152
  state machine had no start state: done() claims success, fail() claims an error, and
153
153
  uploading() is a lie until the consumer actually sends the file. */
@@ -171,12 +171,12 @@
171
171
  bar.style.width = v + '%';
172
172
  progressEl.setAttribute('aria-valuenow', String(Math.round(v)));
173
173
  },
174
- /* The bytes are gone and the server has not answered yet extraction, scanning, transcoding.
174
+ /* The bytes are gone and the server has not answered yet, extraction, scanning, transcoding.
175
175
  "Mengunggah…" turns false the moment the last byte leaves, and a determinate bar parked at
176
176
  100% is the most convincing "hung" signal a UI can produce, so this state reports no
177
177
  percentage: the bar goes indeterminate and the label belongs to the consumer, because only
178
178
  they know what the server is doing ("Membaca PDF…", "Memindai…"). done()/fail()/ready() need
179
- no counterpart here they drop the progress element outright, modifier and all. */
179
+ no counterpart here, they drop the progress element outright, modifier and all. */
180
180
  waiting: function (label) {
181
181
  el.classList.remove('fdy-file--error', 'fdy-file--success');
182
182
  icon.innerHTML = FILE_ICON;
@@ -184,7 +184,7 @@
184
184
  ensureProgress();
185
185
  progressEl.classList.add('fdy-progress--indeterminate');
186
186
  /* The modifier styles .fdy-progress__bar, so it must sit on the CONTAINER, and the inline
187
- width setProgress wrote has to go an inline style beats any rule the modifier brings.
187
+ width setProgress wrote has to go, an inline style beats any rule the modifier brings.
188
188
  aria-valuenow goes with it: a progressbar with no value is precisely what ARIA calls
189
189
  indeterminate, which is the contract COMPONENTS.md already states for this component. */
190
190
  bar.style.width = '';
@@ -255,7 +255,7 @@
255
255
  if (input) input.addEventListener('change', function () { handleFiles(input.files); input.value = ''; });
256
256
 
257
257
  /* The list is optional: rendering a row and announcing the file are separate jobs. A consumer
258
- that wants its own markup simply provides no list it still gets `fdy-upload-add`, and
258
+ that wants its own markup simply provides no list, it still gets `fdy-upload-add`, and
259
259
  `detail.row` still works (its element is just never attached). Gating the EVENT on the list
260
260
  meant "bring your own row" silently cost you the notification that a file had arrived. */
261
261
  function handleFiles(fileList) {