@cahyo-dimas/freeday 1.54.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 +625 -545
- package/COMPONENTS.md +141 -138
- package/README.id.md +46 -45
- package/README.md +46 -43
- package/USAGE.md +34 -34
- package/adapters/blazor/FdyAppShell.razor +2 -2
- package/adapters/blazor/FdyAppShell.razor.cs +6 -6
- 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 +1 -1
- package/adapters/core/app-shell.js +6 -6
- package/adapters/core/table-model.d.ts +2 -2
- package/adapters/core/table-model.js +8 -8
- package/adapters/react/components/FdyAppShell.tsx +5 -5
- 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 +1 -1
- package/adapters/react/useFreeday.js +3 -3
- package/adapters/vue/components/FdyAppShell.vue +5 -5
- 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 +2 -2
- package/adapters/vue/useFreeday.js +3 -3
- package/dist/asset.d.ts +3 -3
- package/dist/freeday-app-shell.js +9 -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 +162 -158
- package/dist/freeday.tokens.css +5 -5
- package/docs/agent-onboarding.md +41 -41
- package/docs/getting-started.md +35 -35
- package/docs/integrations.md +18 -18
- package/docs/reference-screen.html +14 -14
- package/package.json +4 -3
- 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/USAGE.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Freeday — Usage doctrine
|
|
2
2
|
|
|
3
|
-
Freeday ships tokens and components. This file ships the **decisions
|
|
3
|
+
Freeday ships tokens and components. This file ships the **decisions**: which token to use when,
|
|
4
4
|
how a page is assembled, what earns emphasis. A component library enforces consistent *values*; a
|
|
5
5
|
design system also enforces consistent *decisions*. Skim this once before building a screen; it is
|
|
6
6
|
what makes screens built by different people (or different sessions) look like one product.
|
|
7
7
|
|
|
8
|
-
The rules are opinionated on purpose. When one conflicts with a real need, break it deliberately
|
|
8
|
+
The rules are opinionated on purpose. When one conflicts with a real need, break it deliberately, and
|
|
9
9
|
but start here, not from a blank page.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## 1. Type roles
|
|
13
|
+
## 1. Type roles: three title levels, not eleven
|
|
14
14
|
|
|
15
15
|
Do **not** reuse `.fdy-card__title` for a page title. Collapsing page/section/card into one style is
|
|
16
16
|
the single biggest cause of "flat grey mush". Pick the role, not the size:
|
|
@@ -30,31 +30,31 @@ font size.
|
|
|
30
30
|
|
|
31
31
|
## Borders: two roles, two contrast contracts
|
|
32
32
|
|
|
33
|
-
`--color-border` (and `-muted` / `-strong`) is **decoration
|
|
33
|
+
`--color-border` (and `-muted` / `-strong`) is **decoration**: a card edge, a table rule, a
|
|
34
34
|
separator. Nothing in WCAG requires it to be visible, and it is deliberately faint (≈1.3:1).
|
|
35
35
|
|
|
36
|
-
`--color-control-border` is the **boundary of a control
|
|
36
|
+
`--color-control-border` is the **boundary of a control**: input, textarea, checkbox, radio,
|
|
37
37
|
switch, dropzone. WCAG 1.4.11 requires 3:1 against every surface it can sit on, so it is
|
|
38
38
|
necessarily darker than a card edge; that difference is the contract, not an inconsistency.
|
|
39
39
|
|
|
40
40
|
It is tuned to clear that floor with margin (≈3.4–3.9 depending on surface) rather than to be as
|
|
41
41
|
dark as it can be: a boundary that reads as loud as body text makes a form feel heavier than it is.
|
|
42
|
-
Do not "harmonise" a control border down to `--color-border
|
|
42
|
+
Do not "harmonise" a control border down to `--color-border`. That drops a required 3:1 boundary to
|
|
43
43
|
1.3:1.
|
|
44
44
|
|
|
45
|
-
## 2. Spacing rhythm
|
|
45
|
+
## 2. Spacing rhythm: three gaps, always from the scale
|
|
46
46
|
|
|
47
47
|
Never a loose value; always `var(--space-N)` (a 4px scale). Three rhythms carry most layouts, and the
|
|
48
48
|
composition primitives apply them for you:
|
|
49
49
|
|
|
50
|
-
- **Between page sections:** `--space-8
|
|
51
|
-
- **Within a group** (heading ↔ its body, cards in a list): `--space-4
|
|
50
|
+
- **Between page sections:** `--space-8`, which `.fdy-page` sets between its children.
|
|
51
|
+
- **Within a group** (heading ↔ its body, cards in a list): `--space-4`, which `.fdy-page-section` sets.
|
|
52
52
|
- **Inside a control/card** (label ↔ input, icon ↔ text): `--space-2` / `--space-3`.
|
|
53
53
|
|
|
54
54
|
Reserve `--space-1` for hairline pairs and `--space-10`+ for deliberate breathing room (a hero, an
|
|
55
|
-
empty state). Don't scatter `--space-6` everywhere
|
|
55
|
+
empty state). Don't scatter `--space-6` everywhere. A page with one gap value has no rhythm.
|
|
56
56
|
|
|
57
|
-
## 3. Elevation
|
|
57
|
+
## 3. Elevation: most surfaces are flat
|
|
58
58
|
|
|
59
59
|
Shadow is a signal, not decoration. There are two families, and the difference matters:
|
|
60
60
|
|
|
@@ -67,23 +67,23 @@ Shadow is a signal, not decoration. There are two families, and the difference m
|
|
|
67
67
|
| Overlay | `--shadow-4` | `.fdy-drawer` |
|
|
68
68
|
| **Lift** | `--shadow-lift` / `--shadow-lift-hover` | **`.fdy-card`** (and `--elevated` / `--interactive:hover`), `.fdy-modal` |
|
|
69
69
|
|
|
70
|
-
**`.fdy-card` is a lifted surface, not a hairline one
|
|
70
|
+
**`.fdy-card` is a lifted surface, not a hairline one.** `--shadow-lift` is a real 34px lift, ~6×
|
|
71
71
|
heavier than `--shadow-1`. That is the whole point of a card, and it is also why a *stack* of them
|
|
72
72
|
reads wrong: a list of ten cards is ten objects floating off the page. For rows, use the flat
|
|
73
73
|
container **`.fdy-list` / `.fdy-list__row`** (hairline border, `--color-border-muted` dividers, no
|
|
74
74
|
shadow). Reach for `.fdy-card` when something genuinely is one pickable object.
|
|
75
75
|
|
|
76
|
-
If every box on the screen has the same card shadow, none of them read as special
|
|
76
|
+
If every box on the screen has the same card shadow, none of them read as special. That's the
|
|
77
77
|
"identical card grid" failure. Prefer flat sections with **one** raised element that matters.
|
|
78
78
|
|
|
79
|
-
## 4. Emphasis
|
|
79
|
+
## 4. Emphasis: exactly one primary per screen
|
|
80
80
|
|
|
81
81
|
`.fdy-btn` is *already* the primary action (there is no `--primary` modifier). Use it **once** per
|
|
82
|
-
screen
|
|
82
|
+
screen: the one thing you want the user to do. Everything else is `--ghost` or `--text`. Two primary
|
|
83
83
|
buttons on a screen means neither is. The same rule governs colour fills and `--shadow`: one focal
|
|
84
84
|
point, everything around it quiet.
|
|
85
85
|
|
|
86
|
-
## 5. Colour
|
|
86
|
+
## 5. Colour: semantic is reserved; categorical is `--tone`
|
|
87
87
|
|
|
88
88
|
- **Accent** (`--color-primary`, and `--color-accent` sparingly): interactive + brand. This is your
|
|
89
89
|
one accent hue.
|
|
@@ -91,19 +91,19 @@ point, everything around it quiet.
|
|
|
91
91
|
= caution only, `--color-danger` = destructive/error only. Never decorative. Encode state in a pill
|
|
92
92
|
or chip, not just colour.
|
|
93
93
|
- **Categorical** (`--tone-1` … `--tone-8`, the general alias of the validated chart palette): N
|
|
94
|
-
visually-distinct **non-semantic** colours
|
|
94
|
+
visually-distinct **non-semantic** colours: avatar tones, category chips, tags, legend swatches.
|
|
95
95
|
Use the modifiers `.fdy-avatar--tone-N` / `.fdy-chip--tone-N` (both stay WCAG AA in light & dark),
|
|
96
96
|
and hash a stable index off the full string so the same category always gets the same colour.
|
|
97
97
|
- **Surfaces:** most backgrounds are `--color-surface`; `--color-surface-2`/`-3` for a recessed area;
|
|
98
98
|
`--color-primary-soft` only when you want a tinted callout, not as a default panel colour.
|
|
99
99
|
|
|
100
|
-
## 5b. Theme
|
|
100
|
+
## 5b. Theme: global by default, per-subtree when a region is inverted
|
|
101
101
|
|
|
102
102
|
`data-theme="light|dark"` redefines the semantic tokens. Set it on `<html>` and it themes the app;
|
|
103
103
|
that is the normal case and nothing about it has changed.
|
|
104
104
|
|
|
105
105
|
**It is also per-subtree.** The two explicit selectors are bare `[data-theme="dark"]` /
|
|
106
|
-
`[data-theme="light"]`, and semantic tokens are inheriting custom properties
|
|
106
|
+
`[data-theme="light"]`, and semantic tokens are inheriting custom properties, so a
|
|
107
107
|
`<section data-theme="dark">` inverts that region and **every Freeday component inside it follows**:
|
|
108
108
|
card surfaces, inputs, buttons, and text roles like `.fdy-title-page` that set
|
|
109
109
|
`color: var(--color-text)` explicitly. A dark brand panel beside a light sign-in form needs no
|
|
@@ -112,40 +112,40 @@ in turn.
|
|
|
112
112
|
|
|
113
113
|
Do **not** invert a region by hand with `--color-inverse-*` plus `color-mix`. That pair is right for
|
|
114
114
|
a one-off band of your own markup, but it stops scaling the moment the region contains a real
|
|
115
|
-
component
|
|
115
|
+
component. Anything that sets its own colour from a token never sees your override, and you end up
|
|
116
116
|
restating colours per element.
|
|
117
117
|
|
|
118
118
|
The **system** default (`@media (prefers-color-scheme: dark)`) stays root-scoped on purpose: that
|
|
119
119
|
rule is about the document, and un-rooting it would re-darken the children of a light island.
|
|
120
120
|
|
|
121
|
-
## 6. Density
|
|
121
|
+
## 6. Density: `compact` for data-dense screens
|
|
122
122
|
|
|
123
123
|
`data-density="compact"` tightens control height **and** the mid-range spacing scale
|
|
124
124
|
(`--space-3`…`--space-6` step down a notch), so cards, toolbars and tables get denser. Use it on
|
|
125
125
|
table-heavy back-office screens; leave `comfortable` (the default) for forms.
|
|
126
126
|
|
|
127
127
|
**It is per-subtree, not only global.** The selector is a bare `[data-density="compact"]` and these
|
|
128
|
-
are inheriting custom properties, so the attribute works on `<html>` *or* on any wrapper
|
|
128
|
+
are inheriting custom properties, so the attribute works on `<html>` *or* on any wrapper: a route
|
|
129
129
|
container, a single `<section>`. An app whose two list screens are dense and whose three form screens
|
|
130
130
|
are not should scope it per screen rather than densifying everything. Set it at one level per screen,
|
|
131
131
|
never per component.
|
|
132
132
|
|
|
133
133
|
**And it goes both ways.** `data-density="comfortable"` is a real rule, not just the absence of
|
|
134
|
-
`compact`, so an app that is dense *at the root* can opt one region back out
|
|
134
|
+
`compact`, so an app that is dense *at the root* can opt one region back out: a header, a toolbar,
|
|
135
135
|
a footer shared with a sibling product that has to line up pixel for pixel. Inheritance only runs
|
|
136
136
|
downhill; without that rule a compact root left every subtree compact and a `comfortable` wrapper
|
|
137
137
|
changed nothing. Do not restate the five values by hand: that copy goes stale the moment the kit
|
|
138
138
|
retunes a step.
|
|
139
139
|
|
|
140
|
-
## 6b. Navigation: one component, two orientations
|
|
140
|
+
## 6b. Navigation: one component, two orientations, and never a tab role
|
|
141
141
|
|
|
142
142
|
A navigation link is an `<a class="fdy-nav__item">` marked **`aria-current="page"`**. That does not
|
|
143
143
|
change with the layout:
|
|
144
144
|
|
|
145
|
-
- **Sidebar app
|
|
146
|
-
- **Top-nav app
|
|
145
|
+
- **Sidebar app:** `.fdy-nav` inside `.fdy-app__sidebar` (the default).
|
|
146
|
+
- **Top-nav app:** `.fdy-nav.fdy-nav--horizontal` inside `.fdy-appbar` or `.fdy-app__topbar`, with
|
|
147
147
|
no sidebar. Same items, same states; on `.fdy-appbar--primary` the links go on-colour for you.
|
|
148
|
-
- **Routed sub-navigation that should look like tabs** (`/settings/profile` · `/settings/billing`)
|
|
148
|
+
- **Routed sub-navigation that should look like tabs** (`/settings/profile` · `/settings/billing`):
|
|
149
149
|
put `.fdy-tabs__list` / `.fdy-tabs__tab` on plain `<a>`s. Those classes honour `aria-current="page"`
|
|
150
150
|
as well as `aria-selected="true"` precisely for this. Do **not** add `role="tab"`/`role="tablist"`
|
|
151
151
|
or `freeday-tabs.js`: those promise a roving-tabindex, arrow-key, one-panel-per-tab contract that
|
|
@@ -154,16 +154,16 @@ change with the layout:
|
|
|
154
154
|
Reserve the full `.fdy-tabs` component (with its roles and its enhancer) for **in-page** tabs, where
|
|
155
155
|
nothing navigates.
|
|
156
156
|
|
|
157
|
-
**Toggles:** a button that is on/off carries `aria-pressed`, and the kit styles it
|
|
157
|
+
**Toggles:** a button that is on/off carries `aria-pressed`, and the kit styles it: soft primary
|
|
158
158
|
fill on `--ghost`/`--text`, a sunken gradient on the solid button. A `.fdy-btn-group` of `--ghost`
|
|
159
159
|
buttons with exactly one `aria-pressed="true"` **is** the segmented control; don't hand-tint it.
|
|
160
160
|
|
|
161
161
|
## 7. Assemble the page from the frame down
|
|
162
162
|
|
|
163
|
-
1. **Shell:** every application starts inside **`.fdy-app
|
|
163
|
+
1. **Shell:** every application starts inside **`.fdy-app`**, a flex row of `__sidebar` (with
|
|
164
164
|
`__brand` + `.fdy-nav`) and `__content` (which holds `__topbar` + `__main`, plus `__navtoggle`
|
|
165
165
|
and `__backdrop`). The nesting is fixed; don't hand-roll a shell from flexbox. **Take the
|
|
166
|
-
behaviour too
|
|
166
|
+
behaviour too:** `<FdyAppShell>` in Vue/React/Blazor, or `data-fdy-app` plus
|
|
167
167
|
`freeday-app-shell.js` in plain markup. Until 1.53.0 the kit shipped the classes and left every
|
|
168
168
|
consumer to write the toggle, Escape, focus trap, focus restore and `inert` themselves, and the
|
|
169
169
|
two copies in this repo's own docs had already drifted apart; a nav panel you cannot escape from
|
|
@@ -174,22 +174,22 @@ buttons with exactly one `aria-pressed="true"` **is** the segmented control; don
|
|
|
174
174
|
primary action on the right).
|
|
175
175
|
3. **Sections:** each region is a **`.fdy-page-section`** (a `.fdy-title-section` + optional
|
|
176
176
|
`.fdy-toolbar`, then its body).
|
|
177
|
-
**Toolbar or filter bar
|
|
177
|
+
**Toolbar or filter bar? Pick by whether the fields carry visible labels.** `.fdy-toolbar` is
|
|
178
178
|
`align-items:center`, right for bare controls (buttons, a search box, chips); put a labelled
|
|
179
179
|
`.fdy-field` in it and that field sits half a label-height low against its neighbours. Fields
|
|
180
180
|
with visible labels belong in **`.fdy-filterbar`**, which is `align-items:flex-end` for exactly
|
|
181
181
|
this reason (and has the width rhythm `--w-sm`…`--w-grow`). In a toolbar, label fields with
|
|
182
182
|
`.fdy-visually-hidden` or a placeholder.
|
|
183
|
-
4. **KPIs:** a **`.fdy-stats`** grid of **`.fdy-stat`** tiles
|
|
183
|
+
4. **KPIs:** a **`.fdy-stats`** grid of **`.fdy-stat`** tiles, deliberately *not* cards, so a metric
|
|
184
184
|
strip doesn't become an identical-card grid. Wrap in `.fdy-stats--boxed` for one shared strip.
|
|
185
185
|
5. **Content:** components (`.fdy-card`, `.fdy-datatable`, `.fdy-chart`, …) go inside sections.
|
|
186
186
|
|
|
187
187
|
Freeday deliberately owns **components + tokens, not layout**. Everything above is layout in the kit's
|
|
188
188
|
own language; for the rest (grids, one-off spacing), pair a utility framework run **utilities-only,
|
|
189
|
-
preflight-off
|
|
189
|
+
preflight-off**, and build its theme on `var(--space-N)` so the two systems agree. See
|
|
190
190
|
`docs/getting-started.md` §Core concepts.
|
|
191
191
|
|
|
192
192
|
---
|
|
193
193
|
|
|
194
194
|
*Layout classes here live in `src/components/composition.css`. If a screen needs a primitive that
|
|
195
|
-
isn't here, it probably belongs here
|
|
195
|
+
isn't here, it probably belongs here. Open an issue rather than re-inventing it per screen.*
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
@* Blazor wrapper over freeday's .fdy-app shell. Unlike FdyModal and FdyDrawer, which drive a native
|
|
5
5
|
<dialog> through the bridge, this one hands the whole behaviour to freeday-app-shell.js via
|
|
6
6
|
`data-fdy-app` and binds to it: the enhancer announces changes as a bubbling `fdy-app-nav` event
|
|
7
|
-
and accepts them through FreedayAppShell.setVisible. That is the bridge's own doctrine
|
|
8
|
-
enhancers stay the source of truth
|
|
7
|
+
and accepts them through FreedayAppShell.setVisible. That is the bridge's own doctrine: the
|
|
8
|
+
enhancers stay the source of truth, and it keeps the focus trap from existing a third time. *@
|
|
9
9
|
<div @ref="Root" class="fdy-app" data-fdy-app>
|
|
10
10
|
@SkipContent
|
|
11
11
|
|
|
@@ -6,12 +6,12 @@ namespace Freeday.Blazor;
|
|
|
6
6
|
public partial class FdyAppShell
|
|
7
7
|
{
|
|
8
8
|
/// <summary>
|
|
9
|
-
/// Whether the nav is visible to the reader
|
|
9
|
+
/// Whether the nav is visible to the reader, one idea, in both modes: above the nav breakpoint
|
|
10
10
|
/// a hidden nav is a collapsed column, below it a visible nav is an overlay. The kit owns that
|
|
11
11
|
/// mapping so an app never reasons about the viewport to answer a question about its own UI.
|
|
12
12
|
/// <para>
|
|
13
13
|
/// Leave it <c>null</c> (the default) and the shell keeps its own, starting from the viewport:
|
|
14
|
-
/// a column on a wide screen, hidden on a narrow one. That default is why this is nullable
|
|
14
|
+
/// a column on a wide screen, hidden on a narrow one. That default is why this is nullable,
|
|
15
15
|
/// a caller cannot express it as a single initial value before it knows the viewport. Bind it
|
|
16
16
|
/// (<c>@bind-NavOpen</c>) when the app wants to drive it from a menu or a saved preference.
|
|
17
17
|
/// </para>
|
|
@@ -26,7 +26,7 @@ public partial class FdyAppShell
|
|
|
26
26
|
/// <summary>The brand block at the top of the sidebar.</summary>
|
|
27
27
|
[Parameter] public RenderFragment? BrandContent { get; set; }
|
|
28
28
|
|
|
29
|
-
/// <summary>The navigation itself
|
|
29
|
+
/// <summary>The navigation itself, normally a <c>.fdy-nav</c> list.</summary>
|
|
30
30
|
[Parameter] public RenderFragment? NavContent { get; set; }
|
|
31
31
|
|
|
32
32
|
/// <summary>Topbar actions, rendered after the title.</summary>
|
|
@@ -54,7 +54,7 @@ public partial class FdyAppShell
|
|
|
54
54
|
|
|
55
55
|
if (NavOpen is bool wanted)
|
|
56
56
|
{
|
|
57
|
-
// A caller that bound a value is authoritative
|
|
57
|
+
// A caller that bound a value is authoritative, push it down.
|
|
58
58
|
await JS.InvokeVoidAsync("FreedayAppShell.setVisible", Root, wanted);
|
|
59
59
|
_lastNavOpen = wanted;
|
|
60
60
|
}
|
|
@@ -70,7 +70,7 @@ public partial class FdyAppShell
|
|
|
70
70
|
|
|
71
71
|
protected override async Task OnParametersSetAsync()
|
|
72
72
|
{
|
|
73
|
-
// Only reconcile once the shell is wired, and only when the caller actually changed it
|
|
73
|
+
// Only reconcile once the shell is wired, and only when the caller actually changed it,
|
|
74
74
|
// echoing our own event back down would fight the enhancer for the same state.
|
|
75
75
|
if (_navToken != 0 && NavOpen is bool wanted && wanted != _lastNavOpen)
|
|
76
76
|
{
|
|
@@ -79,7 +79,7 @@ public partial class FdyAppShell
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
/// <summary>Invoked by the bridge when the shell's nav visibility changes for any reason
|
|
82
|
+
/// <summary>Invoked by the bridge when the shell's nav visibility changes for any reason,
|
|
83
83
|
/// the toggle, Esc, the backdrop, following a nav link, or the viewport crossing the
|
|
84
84
|
/// breakpoint.</summary>
|
|
85
85
|
[JSInvokable]
|
|
@@ -195,7 +195,7 @@ public partial class FdyCfl<TRow>
|
|
|
195
195
|
else _picked.RemoveAt(at);
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
/* A click means "tick this" in multi and "this is my answer" in single
|
|
198
|
+
/* A click means "tick this" in multi and "this is my answer" in single, the whole difference. */
|
|
199
199
|
private async Task RowClickAsync(TRow row)
|
|
200
200
|
{
|
|
201
201
|
if (Multiple) TogglePick(row);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@* A thin Blazor wrapper over freeday's zero-dependency chart renderer (freeday-chart.js). Charts
|
|
4
4
|
are not form controls, so re-implementing the SVG maths in C# would only duplicate them. Instead
|
|
5
5
|
Blazor owns the outer <div> and its data-* attributes; after every render this calls
|
|
6
|
-
FreedayChart.update() (via the bridge) to repaint the SVG from those attributes
|
|
6
|
+
FreedayChart.update() (via the bridge) to repaint the SVG from those attributes, giving reactive,
|
|
7
7
|
typed charts with no external dependency. Because the renderer paints with CSS var()/--chart-*
|
|
8
8
|
tokens, charts also recolour on data-theme change for free. Requires dist/freeday.js loaded so
|
|
9
9
|
window.FreedayChart exists; until then the slotted fallback content stays visible. *@
|
|
@@ -32,7 +32,7 @@ public partial class FdyChart : ComponentBase
|
|
|
32
32
|
/// <summary>Legend visibility: <c>auto</c> | <c>always</c> | <c>none</c>.</summary>
|
|
33
33
|
[Parameter] public string? Legend { get; set; }
|
|
34
34
|
|
|
35
|
-
/// <summary>Per-series colour override
|
|
35
|
+
/// <summary>Per-series colour override, semantic token names (primary/accent/success/…) or
|
|
36
36
|
/// categorical slots <c>chart-1</c>..<c>chart-8</c>. Omit for the default chart palette.</summary>
|
|
37
37
|
[Parameter] public IReadOnlyList<string>? Colors { get; set; }
|
|
38
38
|
|
|
@@ -72,14 +72,14 @@ public partial class FdyChart : ComponentBase
|
|
|
72
72
|
private string? ColorsAttr => Colors is null ? null : string.Join(",", Colors);
|
|
73
73
|
private string? StackedAttr => Stacked ? string.Empty : null; // presence attribute
|
|
74
74
|
|
|
75
|
-
// Signature of every data-affecting attribute
|
|
75
|
+
// Signature of every data-affecting attribute, the C# analogue of the Vue/React watch list.
|
|
76
76
|
private string DataSignature => string.Join("", Type, SeriesAttr, ValuesAttr, LabelsAttr,
|
|
77
77
|
Format, StackedAttr, Legend, ColorsAttr, Color, Center);
|
|
78
78
|
|
|
79
79
|
private string? _lastSignature;
|
|
80
80
|
|
|
81
81
|
// Repaint only when the chart's own data changed (first render, or a data-* attribute differs
|
|
82
|
-
// since the last paint)
|
|
82
|
+
// since the last paint), so an unrelated parent re-render doesn't needlessly repaint the SVG.
|
|
83
83
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
84
84
|
{
|
|
85
85
|
string sig = DataSignature;
|
|
@@ -3,7 +3,7 @@ using System.Text.Json.Serialization;
|
|
|
3
3
|
namespace Freeday.Blazor;
|
|
4
4
|
|
|
5
5
|
/// <summary>One data series in a multi-series chart (line/area/bar). Serialised to the renderer's
|
|
6
|
-
/// <c>data-series</c> JSON shape <c>{ label, values, role? }</c
|
|
6
|
+
/// <c>data-series</c> JSON shape <c>{ label, values, role? }</c>, hence the camelCase names.</summary>
|
|
7
7
|
public sealed record FdyChartSeries(
|
|
8
8
|
[property: JsonPropertyName("label")] string Label,
|
|
9
9
|
[property: JsonPropertyName("values")] IReadOnlyList<double> Values,
|
|
@@ -34,7 +34,7 @@ public partial class FdyCombo<TValue>
|
|
|
34
34
|
private bool _ready;
|
|
35
35
|
|
|
36
36
|
// The enhancer owns this combo's DOM after hydration (open/close, aria-selected, the button
|
|
37
|
-
// label). Re-rendering here would fight it
|
|
37
|
+
// label). Re-rendering here would fight it, e.g. reconciling the listbox mid-close leaves it
|
|
38
38
|
// stuck open. Render once for the initial markup, then never again; push external Value changes
|
|
39
39
|
// through the enhancer via comboSetValue instead.
|
|
40
40
|
protected override bool ShouldRender() => !Hydrated;
|
|
@@ -60,7 +60,7 @@ public partial class FdyCombo<TValue>
|
|
|
60
60
|
|
|
61
61
|
protected override async Task OnParametersSetAsync()
|
|
62
62
|
{
|
|
63
|
-
// Push an externally-changed Value onto the enhancer-owned DOM (silent
|
|
63
|
+
// Push an externally-changed Value onto the enhancer-owned DOM (silent, no fdy-change echo).
|
|
64
64
|
if (_ready && !EqualityComparer<TValue>.Default.Equals(Value, _lastValue))
|
|
65
65
|
{
|
|
66
66
|
_lastValue = Value;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
@* Controlled wrapper over freeday's .fdy-modal native <dialog>. Blazor can't call
|
|
5
5
|
showModal()/close() from C#, so open/close + Esc/backdrop dismissal route through the
|
|
6
6
|
freeday-blazor.js bridge. Native <dialog> gives the focus trap, focus restore, top-layer
|
|
7
|
-
stacking and inert background for free
|
|
7
|
+
stacking and inert background for free; this only reconciles it with Blazor state. *@
|
|
8
8
|
<dialog @ref="Root" class="@ModalClass" aria-labelledby="@_titleId">
|
|
9
9
|
<div class="fdy-modal__header">
|
|
10
10
|
<h3 id="@_titleId" class="fdy-modal__title">
|
|
@@ -30,8 +30,8 @@ public partial class FdyTable<TRow>
|
|
|
30
30
|
[Parameter] public int PageSize { get; set; }
|
|
31
31
|
|
|
32
32
|
/// <summary>
|
|
33
|
-
/// Controlled client-side page index (0-based). Set it
|
|
34
|
-
/// <see cref="Page"
|
|
33
|
+
/// Controlled client-side page index (0-based). Set it, with <see cref="PageSize"/>, without
|
|
34
|
+
/// <see cref="Page"/>, to own the page while the table keeps doing filter/sort/paginate. That is
|
|
35
35
|
/// what lets an EXTERNAL pager drive the table: a responsive screen that hides the datatable below
|
|
36
36
|
/// the <c>md</c> breakpoint and renders a card list from <see cref="Process"/> can render one pager
|
|
37
37
|
/// for both breakpoints and bind it here. Leave null for the internal index (unchanged default).
|
|
@@ -45,14 +45,14 @@ public partial class FdyTable<TRow>
|
|
|
45
45
|
/// Offer a rows-per-page control in the footer, beside the range and the pager. Leave null for
|
|
46
46
|
/// none (unchanged default). Every back office has one, and a table that renders two thirds of
|
|
47
47
|
/// its own footer forces the app to rebuild all three to add the last (#008).
|
|
48
|
-
/// Server mode reports the pick through <see cref="PageChanged"
|
|
48
|
+
/// Server mode reports the pick through <see cref="PageChanged"/>, same callback as a page
|
|
49
49
|
/// click, with a new size. Client mode applies it internally and also raises
|
|
50
50
|
/// <see cref="PageSizeChanged"/>, so the control works with nothing wired.
|
|
51
51
|
/// </summary>
|
|
52
52
|
[Parameter] public IReadOnlyList<int>? PageSizes { get; set; }
|
|
53
53
|
|
|
54
54
|
/// <summary>Raised in client mode when the reader picks a new rows-per-page. The table has
|
|
55
|
-
/// already applied it
|
|
55
|
+
/// already applied it, this is for a caller that wants to persist the choice.</summary>
|
|
56
56
|
[Parameter] public EventCallback<int> PageSizeChanged { get; set; }
|
|
57
57
|
|
|
58
58
|
[Parameter] public int? PageIndex { get; set; }
|
|
@@ -62,7 +62,7 @@ public partial class FdyTable<TRow>
|
|
|
62
62
|
[Parameter] public EventCallback<int> PageIndexChanged { get; set; }
|
|
63
63
|
|
|
64
64
|
/// <summary>Raised whenever the processed page of rows (after filter/sort/paginate) or the total
|
|
65
|
-
/// changes, in BOTH modes
|
|
65
|
+
/// changes, in BOTH modes, so the same processed set can drive a card list, a summary or an
|
|
66
66
|
/// export without re-deriving the pipeline. Mirrors <c>process</c> in the Vue/React adapters.</summary>
|
|
67
67
|
[Parameter] public EventCallback<FdyTableProcess<TRow>> Process { get; set; }
|
|
68
68
|
|
|
@@ -113,7 +113,7 @@ public partial class FdyTable<TRow>
|
|
|
113
113
|
FiltersControlled ? (Filters ?? EmptyFilters) : _internalFilters;
|
|
114
114
|
|
|
115
115
|
/* Client-mode rows-per-page. PageSize is a plain parameter with no callback, so a footer control
|
|
116
|
-
* that only reported would do nothing in the app that wired nothing
|
|
116
|
+
* that only reported would do nothing in the app that wired nothing, the table applies the pick
|
|
117
117
|
* itself and reports it. An explicit change to the parameter wins back (see OnParametersSet). */
|
|
118
118
|
private int? _internalPageSize;
|
|
119
119
|
private int _prevPageSize;
|
|
@@ -298,7 +298,7 @@ public partial class FdyTable<TRow>
|
|
|
298
298
|
|
|
299
299
|
// Enter/Space activate a focused row. Blazor's KeyboardEventArgs can't tell whether the row
|
|
300
300
|
// itself vs an inner control is the target, so activatable rows should not embed focusable
|
|
301
|
-
// controls (the common drill-in-row pattern)
|
|
301
|
+
// controls (the common drill-in-row pattern), matching the Vue guard's practical effect.
|
|
302
302
|
private async Task OnRowKeydown(KeyboardEventArgs e, TRow row)
|
|
303
303
|
{
|
|
304
304
|
if (!RowActivatable) return;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@* Internal to FdyTable: one column's header funnel button + its type-aware filter popover
|
|
4
4
|
(text / enum / number / date), over freeday's .fdy-table__filterbtn + .fdy-filter* classes.
|
|
5
5
|
The panel is position:fixed (top layer) so it escapes the table's overflow; light-dismiss
|
|
6
|
-
(outside pointer / Esc) is wired through FreedayBlazor.onOutside. Purely controlled
|
|
6
|
+
(outside pointer / Esc) is wired through FreedayBlazor.onOutside. Purely controlled: it renders
|
|
7
7
|
the current Filter and raises the next one (or null to clear). *@
|
|
8
8
|
<span @ref="_root" class="fdy-table__filterwrap">
|
|
9
9
|
<button type="button"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@* The band under a table: what you are looking at, how much of it you see, where you are.
|
|
2
2
|
|
|
3
3
|
FdyTable renders this itself, so most screens never use it directly. It is public for the one
|
|
4
|
-
shape that cannot use the table's own
|
|
4
|
+
shape that cannot use the table's own: a RESPONSIVE list, where a .fdy-datatable at lg and a
|
|
5
5
|
.fdy-list below it are two renderings of ONE page of rows. A footer inside the table is inside the
|
|
6
6
|
half that is hidden on a phone, so those screens render it once, outside both (improvement notes
|
|
7
7
|
#005 and #008, from IDU_EMATE_APPL_WEB). *@
|
|
@@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Components;
|
|
|
3
3
|
namespace Freeday.Blazor;
|
|
4
4
|
|
|
5
5
|
/// <summary>
|
|
6
|
-
/// The table footer
|
|
6
|
+
/// The table footer, range, optional rows-per-page, pager, as a component of its own.
|
|
7
7
|
/// It owns nothing: <see cref="Page"/> in, <see cref="PageChanged"/> out, the same contract as
|
|
8
8
|
/// <c>FdyTable</c>'s server mode.
|
|
9
9
|
/// </summary>
|
|
@@ -15,7 +15,7 @@ public partial class FdyTableFooter
|
|
|
15
15
|
[Parameter] public EventCallback<FdyPageState> PageChanged { get; set; }
|
|
16
16
|
|
|
17
17
|
/// <summary>
|
|
18
|
-
/// Offer a rows-per-page control. Leave null for none
|
|
18
|
+
/// Offer a rows-per-page control. Leave null for none; the footer is then range + pager,
|
|
19
19
|
/// exactly as before. Picking a size raises <see cref="PageChanged"/> with the new size and the
|
|
20
20
|
/// index that still holds the row the reader was looking at.
|
|
21
21
|
/// </summary>
|
|
@@ -28,7 +28,7 @@ public partial class FdyTableFooter
|
|
|
28
28
|
private IReadOnlyList<FdyComboOption<string>> SizeOptions =>
|
|
29
29
|
Sizes.Select(size => new FdyComboOption<string>(size.ToString(), size.ToString())).ToList();
|
|
30
30
|
|
|
31
|
-
// The combo is labelled by the visible word beside it
|
|
31
|
+
// The combo is labelled by the visible word beside it, a <label for> cannot reach inside a
|
|
32
32
|
// component, and an aria-label would leave that word attached to nothing.
|
|
33
33
|
private readonly string SizeLabelId = $"fdy-rows-{Guid.NewGuid():N}";
|
|
34
34
|
|
|
@@ -40,7 +40,7 @@ public partial class FdyTableFooter
|
|
|
40
40
|
|
|
41
41
|
private bool HasPager => Page.Size > 0 && TotalPages > 1;
|
|
42
42
|
|
|
43
|
-
// One page and no size control means there is nothing here to say
|
|
43
|
+
// One page and no size control means there is nothing here to say, the table has always
|
|
44
44
|
// withheld the whole band in that case, and this is where that decision now lives.
|
|
45
45
|
private bool Visible => HasPager || Sizes.Count > 0;
|
|
46
46
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- Freeday
|
|
1
|
+
<!-- Freeday. Blazor component library (Razor Class Library).
|
|
2
2
|
Typed wrappers over the vanilla `fdy-*` enhancers; the host page must load
|
|
3
3
|
dist/freeday.js + adapters/blazor/freeday-blazor.js. Targets net8.0 (LTS) so it can
|
|
4
4
|
be referenced from net8/9/10 apps. Consume via <ProjectReference> to this .csproj
|
|
@@ -36,7 +36,7 @@ public abstract class FreedayComponentBase<TSelf> : ComponentBase, IAsyncDisposa
|
|
|
36
36
|
/// registered enhancer over <see cref="Root"/>; override to call a specific enhancer.</summary>
|
|
37
37
|
protected virtual ValueTask HydrateAsync() => JS.InvokeVoidAsync("FreedayBlazor.initAll", Root);
|
|
38
38
|
|
|
39
|
-
/// <summary>Runs once after the first render, right after <see cref="HydrateAsync"
|
|
39
|
+
/// <summary>Runs once after the first render, right after <see cref="HydrateAsync"/>, wire event
|
|
40
40
|
/// subscriptions here.</summary>
|
|
41
41
|
protected virtual ValueTask OnHydratedAsync() => ValueTask.CompletedTask;
|
|
42
42
|
|
|
@@ -6,7 +6,7 @@ using System.Text.RegularExpressions;
|
|
|
6
6
|
namespace Freeday.Blazor;
|
|
7
7
|
|
|
8
8
|
/// <summary>
|
|
9
|
-
/// The sort / filter / paginate logic for <see cref="FdyTable{TRow}"
|
|
9
|
+
/// The sort / filter / paginate logic for <see cref="FdyTable{TRow}"/>, the C# counterpart of the
|
|
10
10
|
/// framework-agnostic adapters/core/table-model.js shared by the Vue and React adapters. Kept as a
|
|
11
11
|
/// separate pure-function class (no rendering, no state) so it mirrors that reference faithfully and
|
|
12
12
|
/// stays unit-testable. Every method is pure: inputs are never mutated (rows are copied before sort).
|
|
@@ -40,7 +40,7 @@ public static class TableModel
|
|
|
40
40
|
: 0;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/// <summary>ISO calendar day (yyyy-MM-dd)
|
|
43
|
+
/// <summary>ISO calendar day (yyyy-MM-dd), lexicographically comparable.</summary>
|
|
44
44
|
private static string DateOnly(object? v)
|
|
45
45
|
{
|
|
46
46
|
if (v is DateTime dt) return dt.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
|
|
@@ -167,7 +167,7 @@ public static class TableModel
|
|
|
167
167
|
return rows.Skip(pageIndex * pageSize).Take(pageSize).ToList();
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
/// <summary>Distinct non-empty cell texts for a column, naturally sorted
|
|
170
|
+
/// <summary>Distinct non-empty cell texts for a column, naturally sorted, the enum-filter source.</summary>
|
|
171
171
|
public static List<string> DistinctValues<TRow>(IReadOnlyList<TRow> rows, FdyTableColumn<TRow> column)
|
|
172
172
|
{
|
|
173
173
|
HashSet<string> seen = new();
|
|
@@ -5,7 +5,7 @@ namespace Freeday.Blazor;
|
|
|
5
5
|
/// <summary>Sort direction for a column.</summary>
|
|
6
6
|
public enum FdySortDir { Asc, Desc }
|
|
7
7
|
|
|
8
|
-
/// <summary>A column's comparator type
|
|
8
|
+
/// <summary>A column's comparator type, how its values are ordered when sorting.</summary>
|
|
9
9
|
public enum FdyColumnType { Text, Number, Date }
|
|
10
10
|
|
|
11
11
|
/// <summary>Cell alignment. Maps to <c>text-align</c> on the header and body cells.</summary>
|
|
@@ -23,7 +23,7 @@ public sealed record FdyPageState(int Index, int Size, int Total);
|
|
|
23
23
|
|
|
24
24
|
/// <summary>The processed page of rows (after filter/sort/paginate) plus the total row count, as
|
|
25
25
|
/// raised by <see cref="FdyTable{TRow}.Process"/>. Lets a consumer render the same processed set
|
|
26
|
-
/// somewhere else
|
|
26
|
+
/// somewhere else, a card list below the <c>md</c> breakpoint, a summary, an export, without
|
|
27
27
|
/// re-deriving the pipeline. Mirrors the <c>process</c> event in the Vue/React adapters.</summary>
|
|
28
28
|
public sealed record FdyTableProcess<TRow>(IReadOnlyList<TRow> Rows, int Total);
|
|
29
29
|
|
|
@@ -47,7 +47,7 @@ public sealed class FdyTableColumn<TRow>
|
|
|
47
47
|
/// <summary>Header label.</summary>
|
|
48
48
|
public required string Label { get; init; }
|
|
49
49
|
|
|
50
|
-
/// <summary>Render the label for assistive tech only
|
|
50
|
+
/// <summary>Render the label for assistive tech only, the header cell looks empty.
|
|
51
51
|
/// For a column of row CONTROLS (an edit button, a row menu), where a visible heading is noise
|
|
52
52
|
/// above a column of icons but the column still has to be named: a <c>th</c> with no text is
|
|
53
53
|
/// announced as nothing, and a reader tabbing the header row cannot tell what it is. The label
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Freeday
|
|
1
|
+
/* Freeday. Blazor JS interop (classic IIFE; registers window.FreedayBlazor).
|
|
2
2
|
* Consistent with the other Freeday enhancers (plain <script>, no ES module),
|
|
3
3
|
* so it serves from any static host without module-MIME strictness.
|
|
4
4
|
*
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Subscribe to a daterange's child datepicker changes, forwarding {value, role} so a Blazor
|
|
59
|
-
// wrapper can bind From/To separately
|
|
59
|
+
// wrapper can bind From/To separately, both children emit the same fdy-datepicker-change, so
|
|
60
60
|
// the originating child's data-role is what tells them apart.
|
|
61
61
|
function dateRangeOn(element, dotNetRef, methodName) {
|
|
62
62
|
var handler = function (e) {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
return token;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
// Fire a .NET callback when a pointerdown lands outside `element`, or Escape is pressed
|
|
75
|
+
// Fire a .NET callback when a pointerdown lands outside `element`, or Escape is pressed,
|
|
76
76
|
// the light-dismiss primitive for Blazor-owned popovers (e.g. FdyTable's column filter, which
|
|
77
77
|
// is position:fixed in the top layer and so escapes the table's overflow). Returns an off() token.
|
|
78
78
|
function onOutside(element, dotNetRef, methodName) {
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
// Passthrough to the Freeday toast API.
|
|
101
101
|
function toast(options) {
|
|
102
|
-
/* The enhancer's own default is Indonesian
|
|
102
|
+
/* The enhancer's own default is Indonesian, deliberate for the raw path, wrong for a Blazor
|
|
103
103
|
* app, which COMPONENTS.md promises is English throughout. Defaulted here so the promise is
|
|
104
104
|
* kept without changing what a hand-written page gets. */
|
|
105
105
|
options = options || {};
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
if (dismissible) dotNetRef.invokeMethodAsync(dismissMethod);
|
|
141
141
|
};
|
|
142
142
|
var onClick = function (e) {
|
|
143
|
-
// The ::backdrop is not a separate element
|
|
143
|
+
// The ::backdrop is not a separate element, a click whose target is the dialog box
|
|
144
144
|
// itself (not its content) is a backdrop click.
|
|
145
145
|
if (dismissible && e.target === dialog) dotNetRef.invokeMethodAsync(dismissMethod);
|
|
146
146
|
};
|
|
@@ -11,7 +11,7 @@ export interface FdyShellParts {
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* What the DOM should reflect right now.
|
|
14
|
-
* `navVisible` is the single idea the app owns
|
|
14
|
+
* `navVisible` is the single idea the app owns: is the nav showing? `overlay` is whether the
|
|
15
15
|
* viewport is currently below the nav breakpoint, where a visible nav covers the page.
|
|
16
16
|
*/
|
|
17
17
|
export interface FdyShellState {
|