@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.
- package/CHANGELOG.md +657 -535
- package/COMPONENTS.md +153 -135
- package/README.id.md +46 -45
- package/README.md +46 -43
- package/USAGE.md +39 -35
- package/adapters/blazor/FdyAppShell.razor +50 -0
- package/adapters/blazor/FdyAppShell.razor.cs +114 -0
- package/adapters/blazor/FdyCfl.razor.cs +1 -1
- package/adapters/blazor/FdyChart.razor +1 -1
- package/adapters/blazor/FdyChart.razor.cs +3 -3
- package/adapters/blazor/FdyChartSeries.cs +1 -1
- package/adapters/blazor/FdyCombo.razor.cs +2 -2
- package/adapters/blazor/FdyModal.razor +1 -1
- package/adapters/blazor/FdyTable.razor.cs +7 -7
- package/adapters/blazor/FdyTableFilter.razor +1 -1
- package/adapters/blazor/FdyTableFooter.razor +1 -1
- package/adapters/blazor/FdyTableFooter.razor.cs +4 -4
- package/adapters/blazor/Freeday.Blazor.csproj +1 -1
- package/adapters/blazor/FreedayComponentBase.cs +1 -1
- package/adapters/blazor/TableModel.cs +3 -3
- package/adapters/blazor/TableTypes.cs +3 -3
- package/adapters/blazor/freeday-blazor.js +5 -5
- package/adapters/core/app-shell.d.ts +30 -0
- package/adapters/core/app-shell.js +134 -0
- package/adapters/core/table-model.d.ts +2 -2
- package/adapters/core/table-model.js +8 -8
- package/adapters/react/components/FdyAppShell.tsx +159 -0
- package/adapters/react/components/FdyAutocomplete.tsx +1 -1
- package/adapters/react/components/FdyCascade.tsx +1 -1
- package/adapters/react/components/FdyCfl.tsx +11 -11
- package/adapters/react/components/FdyDateRange.tsx +2 -2
- package/adapters/react/components/FdyDatepicker.tsx +5 -5
- package/adapters/react/components/FdyDrawer.tsx +1 -1
- package/adapters/react/components/FdyModal.tsx +2 -2
- package/adapters/react/components/FdyTable.tsx +7 -7
- package/adapters/react/components/FdyTableFilter.tsx +1 -1
- package/adapters/react/components/FdyTableFooter.tsx +5 -5
- package/adapters/react/index.d.ts +2 -1
- package/adapters/react/index.js +1 -0
- package/adapters/react/useFreeday.js +3 -3
- package/adapters/vue/components/FdyAppShell.vue +160 -0
- package/adapters/vue/components/FdyAutocomplete.vue +1 -1
- package/adapters/vue/components/FdyCascade.vue +1 -1
- package/adapters/vue/components/FdyCfl.vue +8 -8
- package/adapters/vue/components/FdyChart.vue +2 -2
- package/adapters/vue/components/FdyCombo.vue +1 -1
- package/adapters/vue/components/FdyDateRange.vue +2 -2
- package/adapters/vue/components/FdyDatepicker.vue +5 -5
- package/adapters/vue/components/FdyDrawer.vue +3 -3
- package/adapters/vue/components/FdyModal.vue +3 -3
- package/adapters/vue/components/FdyTable.vue +7 -7
- package/adapters/vue/components/FdyTableFilter.vue +1 -1
- package/adapters/vue/components/FdyTableFooter.vue +5 -5
- package/adapters/vue/index.d.ts +3 -2
- package/adapters/vue/index.js +1 -0
- package/adapters/vue/useFreeday.js +3 -3
- package/dist/asset.d.ts +3 -3
- package/dist/freeday-app-shell.js +49 -9
- package/dist/freeday-autocomplete.js +2 -2
- package/dist/freeday-breakpoint.js +1 -1
- package/dist/freeday-carousel.js +5 -5
- package/dist/freeday-cascade.js +7 -7
- package/dist/freeday-cfl.js +9 -9
- package/dist/freeday-chart.js +11 -11
- package/dist/freeday-chip.js +3 -3
- package/dist/freeday-datepicker.js +11 -7
- package/dist/freeday-datetime.js +5 -5
- package/dist/freeday-drawer.js +1 -1
- package/dist/freeday-form.js +14 -14
- package/dist/freeday-mask.js +6 -6
- package/dist/freeday-menu.js +1 -1
- package/dist/freeday-number.js +3 -3
- package/dist/freeday-popover.js +3 -3
- package/dist/freeday-rating.js +2 -2
- package/dist/freeday-select.js +5 -5
- package/dist/freeday-slider.js +2 -2
- package/dist/freeday-stepper.js +7 -7
- package/dist/freeday-table.js +15 -15
- package/dist/freeday-tabs.js +1 -1
- package/dist/freeday-timepicker.js +2 -2
- package/dist/freeday-toast.js +8 -8
- package/dist/freeday-tree.js +3 -3
- package/dist/freeday-upload.js +25 -25
- package/dist/freeday.bundle.css +176 -176
- package/dist/freeday.css +170 -170
- package/dist/freeday.d.ts +2 -2
- package/dist/freeday.js +202 -158
- package/dist/freeday.tokens.css +5 -5
- package/docs/agent-onboarding.md +42 -42
- package/docs/getting-started.md +35 -35
- package/docs/integrations.md +18 -18
- package/docs/reference-screen.html +14 -14
- package/package.json +5 -4
- package/src/base.css +6 -6
- package/src/components/accordion.css +4 -4
- package/src/components/alert.css +1 -1
- package/src/components/app-shell.css +10 -10
- package/src/components/appbar.css +3 -3
- package/src/components/autocomplete.css +1 -1
- package/src/components/avatar.css +3 -3
- package/src/components/badge.css +5 -5
- package/src/components/breadcrumb.css +1 -1
- package/src/components/breakpoints.css +4 -4
- package/src/components/button.css +13 -13
- package/src/components/card.css +8 -8
- package/src/components/carousel.css +2 -2
- package/src/components/cascade.css +2 -2
- package/src/components/cfl.css +4 -4
- package/src/components/chart.css +3 -3
- package/src/components/chip.css +2 -2
- package/src/components/combo.css +3 -3
- package/src/components/composition.css +7 -7
- package/src/components/datepicker.css +6 -6
- package/src/components/datetimepicker.css +1 -1
- package/src/components/description-list.css +1 -1
- package/src/components/divider.css +1 -1
- package/src/components/drawer.css +1 -1
- package/src/components/file-upload.css +5 -5
- package/src/components/filterbar.css +7 -7
- package/src/components/form-grid.css +2 -2
- package/src/components/input-group.css +6 -6
- package/src/components/input.css +6 -6
- package/src/components/kbd.css +1 -1
- package/src/components/list.css +6 -6
- package/src/components/menu.css +3 -3
- package/src/components/modal.css +1 -1
- package/src/components/pagination.css +1 -1
- package/src/components/progress.css +1 -1
- package/src/components/rating.css +2 -2
- package/src/components/selection.css +4 -4
- package/src/components/skeleton.css +1 -1
- package/src/components/slider.css +1 -1
- package/src/components/spinner.css +1 -1
- package/src/components/states.css +1 -1
- package/src/components/stepper.css +2 -2
- package/src/components/table.css +15 -15
- package/src/components/tabs.css +3 -3
- package/src/components/timeline.css +1 -1
- package/src/components/timepicker.css +1 -1
- package/src/components/toast.css +3 -3
- package/src/components/tooltip.css +1 -1
- package/src/components/tree.css +2 -2
- package/tokens/breakpoints.d.ts +2 -2
- package/tokens/breakpoints.mjs +3 -3
- package/tokens/tokens.json +1 -1
package/dist/freeday-mask.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
55
|
-
* path
|
|
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: '
|
|
60
|
-
hide: '
|
|
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
|
|
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. */
|
package/dist/freeday-menu.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Freeday
|
|
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].
|
package/dist/freeday-number.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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 }));
|
package/dist/freeday-popover.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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();
|
package/dist/freeday-rating.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
4
|
+
* The radios are native, arrow-key selection and form association come for free.
|
|
5
5
|
*/
|
|
6
6
|
(function () {
|
|
7
7
|
'use strict';
|
package/dist/freeday-select.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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
|
|
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(); });
|
package/dist/freeday-slider.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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';
|
package/dist/freeday-stepper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
23
|
-
* path
|
|
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: '
|
|
28
|
-
next: '
|
|
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
|
|
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. */
|
package/dist/freeday-table.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
38
|
-
* path
|
|
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: '
|
|
43
|
-
next: '
|
|
44
|
-
selected: '{n}
|
|
45
|
-
filter: 'Filter
|
|
46
|
-
filterText: '
|
|
47
|
-
filterTextPlaceholder: '
|
|
48
|
-
filterEnum: '
|
|
49
|
-
filterRange: '
|
|
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: '
|
|
52
|
-
rows: '{n}
|
|
53
|
-
info: '
|
|
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
|
|
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. */
|
package/dist/freeday-tabs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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') || '
|
|
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;
|
package/dist/freeday-toast.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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
|
|
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
|
|
81
|
-
* path
|
|
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: '
|
|
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
|
|
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. */
|
package/dist/freeday-tree.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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"]');
|
package/dist/freeday-upload.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
/* Freeday
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
55
|
-
* path
|
|
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: '
|
|
60
|
-
progress: '
|
|
61
|
-
uploading: '
|
|
62
|
-
waiting: '
|
|
63
|
-
done: '
|
|
64
|
-
badType: '
|
|
65
|
-
tooBig: '
|
|
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
|
|
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 = '×';
|
|
105
105
|
remove.addEventListener('click', function () {
|
|
106
|
-
/* Dispatched on the ZONE, not on the row
|
|
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
|
|
111
|
-
anyone delegating on a common ancestor, two `remove`s
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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) {
|