@gjsify/adwaita-web 0.31.0 → 0.32.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/dist/adwaita-web.css +786 -272
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-about-dialog.spec.d.ts +1 -0
- package/lib/types/adw-action-rows.spec.d.ts +1 -0
- package/lib/types/adw-avatar.spec.d.ts +1 -0
- package/lib/types/adw-banner.spec.d.ts +1 -0
- package/lib/types/adw-button-content.spec.d.ts +1 -0
- package/lib/types/adw-carousel.spec.d.ts +1 -0
- package/lib/types/adw-checks.spec.d.ts +1 -0
- package/lib/types/adw-header-bar.spec.d.ts +1 -0
- package/lib/types/adw-icon.spec.d.ts +1 -0
- package/lib/types/adw-progress-bar.spec.d.ts +1 -0
- package/lib/types/adw-sidebar.spec.d.ts +1 -0
- package/lib/types/adw-switch.spec.d.ts +1 -0
- package/lib/types/adw-wrap-box.spec.d.ts +1 -0
- package/lib/types/bottom-sheet.spec.d.ts +1 -0
- package/lib/types/breakpoints.d.ts +22 -0
- package/lib/types/breakpoints.spec.d.ts +1 -0
- package/lib/types/chrome.spec.d.ts +1 -0
- package/lib/types/elements/adw-about-dialog.d.ts +47 -8
- package/lib/types/elements/adw-action-row.d.ts +35 -0
- package/lib/types/elements/adw-avatar.d.ts +11 -0
- package/lib/types/elements/adw-bottom-sheet.d.ts +33 -4
- package/lib/types/elements/adw-button-content.d.ts +12 -0
- package/lib/types/elements/adw-button-row.d.ts +10 -1
- package/lib/types/elements/adw-carousel.d.ts +111 -8
- package/lib/types/elements/adw-checks.d.ts +57 -0
- package/lib/types/elements/adw-clamp.d.ts +4 -1
- package/lib/types/elements/adw-data-grid.d.ts +11 -31
- package/lib/types/elements/adw-drop-down.d.ts +17 -20
- package/lib/types/elements/adw-entry-row.d.ts +93 -3
- package/lib/types/elements/adw-expander-row.d.ts +7 -1
- package/lib/types/elements/adw-header-bar.d.ts +15 -0
- package/lib/types/elements/adw-icon.d.ts +25 -0
- package/lib/types/elements/adw-inline-view-switcher.d.ts +37 -11
- package/lib/types/elements/adw-menu-button.d.ts +6 -6
- package/lib/types/elements/adw-navigation-split-view.d.ts +6 -0
- package/lib/types/elements/adw-navigation-view.d.ts +63 -20
- package/lib/types/elements/adw-overlay-split-view.d.ts +38 -0
- package/lib/types/elements/adw-password-entry-row.d.ts +19 -10
- package/lib/types/elements/adw-popover.d.ts +58 -0
- package/lib/types/elements/adw-preferences-dialog.d.ts +57 -2
- package/lib/types/elements/adw-preferences-group.d.ts +31 -0
- package/lib/types/elements/adw-progress-bar.d.ts +38 -0
- package/lib/types/elements/adw-sidebar.d.ts +37 -5
- package/lib/types/elements/adw-split-button.d.ts +53 -7
- package/lib/types/elements/adw-switch-row.d.ts +11 -2
- package/lib/types/elements/adw-switch.d.ts +15 -0
- package/lib/types/elements/adw-tab-view.d.ts +129 -12
- package/lib/types/elements/adw-toolbar-view.d.ts +5 -0
- package/lib/types/elements/adw-view-stack.d.ts +27 -19
- package/lib/types/elements/adw-view-switcher-bar.d.ts +23 -7
- package/lib/types/elements/adw-view-switcher.d.ts +22 -11
- package/lib/types/elements/adw-window-title.d.ts +3 -1
- package/lib/types/elements/view-switcher-dom.d.ts +44 -0
- package/lib/types/entry-rows.spec.d.ts +1 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/navigation-view.spec.d.ts +1 -0
- package/lib/types/preferences-search.d.ts +20 -0
- package/lib/types/preferences.spec.d.ts +1 -0
- package/lib/types/split-button.spec.d.ts +1 -0
- package/lib/types/split-views.spec.d.ts +1 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/lib/types/tab-view.spec.d.ts +1 -0
- package/lib/types/view-stack.spec.d.ts +1 -0
- package/lib/types/view-switcher.spec.d.ts +1 -0
- package/package.json +6 -6
- package/scss/_banner.scss +13 -0
- package/scss/_bottom_sheet.scss +5 -6
- package/scss/_button.scss +3 -26
- package/scss/_button_content.scss +28 -0
- package/scss/_checks.scss +228 -0
- package/scss/_clamp.scss +9 -3
- package/scss/_data_grid.scss +15 -7
- package/scss/_drop_down.scss +12 -55
- package/scss/_expander_row.scss +5 -50
- package/scss/_icon.scss +51 -0
- package/scss/_icons.generated.scss +6 -0
- package/scss/_inline_view_switcher.scss +34 -0
- package/scss/_labels.scss +135 -0
- package/scss/_menu_button.scss +10 -70
- package/scss/_popover.scss +186 -0
- package/scss/_preferences.scss +29 -0
- package/scss/_preferences_dialog.scss +17 -0
- package/scss/_progress_bar.scss +161 -0
- package/scss/_reset.scss +18 -7
- package/scss/_spinner.scss +7 -3
- package/scss/_split_button.scss +6 -50
- package/scss/_switch.scss +90 -0
- package/scss/_switch_row.scss +6 -52
- package/scss/_tab_view.scss +64 -0
- package/scss/_theme.scss +10 -0
- package/scss/_toolbar_view.scss +74 -0
- package/scss/_variables.scss +34 -0
- package/scss/_view_switcher.scss +40 -0
- package/scss/_view_switcher_bar.scss +37 -0
- package/scss/_wrap_box.scss +56 -6
- package/scss/adwaita-skin.scss +23 -0
- package/src/adw-about-dialog.spec.ts +350 -0
- package/src/adw-action-rows.spec.ts +342 -0
- package/src/adw-avatar.spec.ts +139 -0
- package/src/adw-banner.spec.ts +152 -0
- package/src/adw-button-content.spec.ts +183 -0
- package/src/adw-button-row.spec.ts +12 -6
- package/src/adw-carousel.spec.ts +389 -0
- package/src/adw-checks.spec.ts +368 -0
- package/src/adw-drop-down.spec.ts +123 -0
- package/src/adw-header-bar.spec.ts +83 -0
- package/src/adw-icon.spec.ts +167 -0
- package/src/adw-progress-bar.spec.ts +173 -0
- package/src/adw-sidebar.spec.ts +332 -0
- package/src/adw-switch.spec.ts +242 -0
- package/src/adw-tab-view.spec.ts +12 -3
- package/src/adw-view-switcher-bar.spec.ts +61 -13
- package/src/adw-wrap-box.spec.ts +194 -0
- package/src/bottom-sheet.spec.ts +325 -0
- package/src/breakpoints.spec.ts +147 -0
- package/src/breakpoints.ts +67 -0
- package/src/chrome.spec.ts +301 -0
- package/src/elements/adw-about-dialog.ts +223 -163
- package/src/elements/adw-action-row.ts +120 -10
- package/src/elements/adw-avatar.ts +48 -54
- package/src/elements/adw-banner.ts +46 -10
- package/src/elements/adw-bottom-sheet.ts +145 -60
- package/src/elements/adw-button-content.ts +107 -33
- package/src/elements/adw-button-row.ts +61 -37
- package/src/elements/adw-button.ts +5 -7
- package/src/elements/adw-carousel.ts +467 -105
- package/src/elements/adw-checks.ts +299 -0
- package/src/elements/adw-clamp.ts +80 -10
- package/src/elements/adw-combo-row.ts +15 -7
- package/src/elements/adw-data-grid.ts +43 -91
- package/src/elements/adw-drop-down.ts +117 -128
- package/src/elements/adw-entry-row.ts +404 -36
- package/src/elements/adw-expander-row.ts +61 -29
- package/src/elements/adw-header-bar.ts +31 -6
- package/src/elements/adw-icon.ts +148 -0
- package/src/elements/adw-inline-view-switcher.ts +240 -129
- package/src/elements/adw-menu-button.ts +93 -70
- package/src/elements/adw-navigation-split-view.ts +48 -7
- package/src/elements/adw-navigation-view.ts +286 -148
- package/src/elements/adw-overlay-split-view.ts +164 -14
- package/src/elements/adw-password-entry-row.ts +111 -89
- package/src/elements/adw-popover.ts +283 -0
- package/src/elements/adw-preferences-dialog.ts +120 -21
- package/src/elements/adw-preferences-group.ts +128 -22
- package/src/elements/adw-progress-bar.ts +189 -0
- package/src/elements/adw-sidebar.ts +301 -142
- package/src/elements/adw-spin-row.ts +11 -5
- package/src/elements/adw-spinner.ts +23 -8
- package/src/elements/adw-split-button.ts +371 -92
- package/src/elements/adw-status-page.ts +9 -9
- package/src/elements/adw-switch-row.ts +100 -30
- package/src/elements/adw-switch.ts +129 -0
- package/src/elements/adw-tab-view.ts +682 -129
- package/src/elements/adw-toggle-group.ts +5 -7
- package/src/elements/adw-toolbar-view.ts +84 -21
- package/src/elements/adw-view-stack.ts +162 -85
- package/src/elements/adw-view-switcher-bar.ts +163 -81
- package/src/elements/adw-view-switcher.ts +231 -112
- package/src/elements/adw-window-title.ts +44 -11
- package/src/elements/adw-wrap-box.ts +131 -35
- package/src/elements/view-switcher-dom.ts +108 -0
- package/src/entry-rows.spec.ts +391 -0
- package/src/index.ts +23 -0
- package/src/navigation-view.spec.ts +435 -0
- package/src/preferences-search.ts +135 -0
- package/src/preferences.spec.ts +250 -0
- package/src/source-view/adw-source-view.ts +2 -5
- package/src/split-button.spec.ts +470 -0
- package/src/split-views.spec.ts +309 -0
- package/src/styles.generated.ts +1 -1
- package/src/tab-view.spec.ts +451 -0
- package/src/test.browser.mts +49 -0
- package/src/view-stack.spec.ts +272 -0
- package/src/view-switcher.spec.ts +446 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// <adw-checkbox> and <adw-radio> — the two form-control primitives, in ONE
|
|
2
|
+
// module, for the same reason `scss/_checks.scss` is one partial: upstream
|
|
3
|
+
// merges them (`refs/libadwaita/src/stylesheet/widgets/_checks.scss` has no
|
|
4
|
+
// `_radio.scss` beside it), and everything but the corner radius, the glyph and
|
|
5
|
+
// the group is shared. `refs/adwaita-web` split them into two files and the two
|
|
6
|
+
// promptly drifted apart.
|
|
7
|
+
//
|
|
8
|
+
// WHAT LIVES IN `@gjsify/adwaita-core`, AND WHAT DOES NOT
|
|
9
|
+
//
|
|
10
|
+
// The checkbox has no core class: it is one boolean plus a third state, which
|
|
11
|
+
// ADR 0004 calls out as too trivial to model. What IS core is the pair of
|
|
12
|
+
// pieces a second renderer would otherwise re-invent:
|
|
13
|
+
//
|
|
14
|
+
// - {@link RadioGroupState} — group exclusivity. The browser gives the inner
|
|
15
|
+
// `<input type="radio" name="…">` exclusivity for free, and STOPS THERE: it
|
|
16
|
+
// unchecks the sibling INPUT and leaves the sibling `<adw-radio>` host's
|
|
17
|
+
// `checked` attribute — the published state, and the selector
|
|
18
|
+
// `_checks.scss` paints from — stale, so a group left to the browser draws
|
|
19
|
+
// two selected radios. The shared state is what repaints the loser.
|
|
20
|
+
// - {@link resolveCheckState} — indeterminate outranks checked, which is read
|
|
21
|
+
// off the cascade in `_checks.scss:79-81` and is what `aria-checked` needs.
|
|
22
|
+
//
|
|
23
|
+
// WHAT IS NOT VERIFIABLE IN THIS TREE. `GtkCheckButton` is a GTK widget:
|
|
24
|
+
// `refs/gtk` is EMPTY here and libadwaita vendors no `adw-checkbox.c`, so its
|
|
25
|
+
// group semantics (`gtk_check_button_set_group`, whether a fresh group starts
|
|
26
|
+
// with a member active) and the exact meaning of `GtkCheckButton:inconsistent`
|
|
27
|
+
// are NOT verifiable and are not guessed at. Where a rule was needed the HTML
|
|
28
|
+
// one is used and cited as such — clearing `indeterminate` on activation is the
|
|
29
|
+
// HTML pre-click activation step, not a reading of GTK.
|
|
30
|
+
//
|
|
31
|
+
// NAMING. The state attribute is `checked`, not GtkCheckButton's `active`:
|
|
32
|
+
// these elements wrap a real `<input>`, `checked` is the spelling every author
|
|
33
|
+
// already writes, and it is what the stylesheet selects on. The published event
|
|
34
|
+
// follows the attribute (`notify::checked`), not the GObject property.
|
|
35
|
+
//
|
|
36
|
+
// Attributes (both):
|
|
37
|
+
// checked — boolean; reflects (and drives) the checked state.
|
|
38
|
+
// indeterminate — boolean; the third state, drawn as a dash. Outranks checked.
|
|
39
|
+
// disabled — boolean; the control does not respond and is dimmed.
|
|
40
|
+
// label — the text beside the indicator. When absent, the element's
|
|
41
|
+
// existing child nodes become the label (so a server-rendered
|
|
42
|
+
// `<adw-checkbox>Enable</adw-checkbox>` upgrades intact).
|
|
43
|
+
// Attributes (<adw-radio> only):
|
|
44
|
+
// name — the group. Exclusivity is scoped to it, exactly as `name`
|
|
45
|
+
// scopes `<input type="radio">` — including the empty case:
|
|
46
|
+
// HTML forms a radio button group only from a NON-EMPTY name,
|
|
47
|
+
// so a nameless radio checks itself and unchecks nothing.
|
|
48
|
+
// value — this member's value. Defaults to the label text, so a group
|
|
49
|
+
// written without values still has distinguishable members.
|
|
50
|
+
// Properties: checked / indeterminate / disabled / label (+ name / value).
|
|
51
|
+
// Events:
|
|
52
|
+
// `notify::checked` (CustomEvent, bubbles, detail = { checked }) — fires on
|
|
53
|
+
// every change, programmatic included, on EVERY member a radio pick moves.
|
|
54
|
+
//
|
|
55
|
+
// A11Y: the inner input carries the role (native `checkbox` / `radio`) and an
|
|
56
|
+
// explicit `aria-checked` derived from {@link resolveCheckState}, so the
|
|
57
|
+
// indeterminate state announces as `mixed` for BOTH — HTML has a native mixed
|
|
58
|
+
// checkbox (`input.indeterminate`) but no mixed radio.
|
|
59
|
+
//
|
|
60
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_checks.scss
|
|
61
|
+
// Reference: refs/adwaita-web/adwaita-web/scss/{_checkbox,_radio}.scss
|
|
62
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
63
|
+
// Copyright (c) 2025 csm (adwaita-web). MIT License.
|
|
64
|
+
// Modifications: Implemented as Web Components for @gjsify/adwaita-web.
|
|
65
|
+
|
|
66
|
+
import { RadioGroupState, resolveCheckState } from '@gjsify/adwaita-core';
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The document's radio groups. ONE registry, as global as a bare
|
|
70
|
+
* `<input type="radio" name="x">` outside a form is — two independent groups
|
|
71
|
+
* therefore need two names.
|
|
72
|
+
*/
|
|
73
|
+
const radioGroups = new RadioGroupState();
|
|
74
|
+
|
|
75
|
+
/** The markup + state shared by `<adw-checkbox>` and `<adw-radio>`. */
|
|
76
|
+
abstract class AdwCheckBase extends HTMLElement {
|
|
77
|
+
protected _input!: HTMLInputElement;
|
|
78
|
+
protected _indicator!: HTMLSpanElement;
|
|
79
|
+
protected _label!: HTMLSpanElement;
|
|
80
|
+
private _initialized = false;
|
|
81
|
+
|
|
82
|
+
/** `checkbox` or `radio` — the native control this element is built around. */
|
|
83
|
+
protected abstract get inputType(): 'checkbox' | 'radio';
|
|
84
|
+
|
|
85
|
+
/** What a click / Space / arrow key on the control means for this kind. */
|
|
86
|
+
protected abstract activate(): void;
|
|
87
|
+
|
|
88
|
+
/** Whether the control is checked. */
|
|
89
|
+
get checked(): boolean {
|
|
90
|
+
return this.hasAttribute('checked');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
set checked(value: boolean) {
|
|
94
|
+
// `toggleAttribute` with a force flag is a no-op when the attribute
|
|
95
|
+
// already holds that state, so re-setting the current value mutates
|
|
96
|
+
// nothing and the notify never runs.
|
|
97
|
+
this.toggleAttribute('checked', !!value);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Whether the control is in the third, inconsistent state. */
|
|
101
|
+
get indeterminate(): boolean {
|
|
102
|
+
return this.hasAttribute('indeterminate');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
set indeterminate(value: boolean) {
|
|
106
|
+
this.toggleAttribute('indeterminate', !!value);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Whether the control is inert. */
|
|
110
|
+
get disabled(): boolean {
|
|
111
|
+
return this.hasAttribute('disabled');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
set disabled(value: boolean) {
|
|
115
|
+
this.toggleAttribute('disabled', !!value);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The label text beside the indicator. */
|
|
119
|
+
get label(): string {
|
|
120
|
+
return this.getAttribute('label') ?? this._label?.textContent ?? '';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
set label(value: string) {
|
|
124
|
+
this.setAttribute('label', value);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
connectedCallback() {
|
|
128
|
+
if (this._initialized) {
|
|
129
|
+
this.onConnected();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
this._initialized = true;
|
|
133
|
+
|
|
134
|
+
// Captured BEFORE the element takes over its own children: a
|
|
135
|
+
// server-rendered `<adw-checkbox>Enable</adw-checkbox>` keeps its text.
|
|
136
|
+
const authored = [...this.childNodes];
|
|
137
|
+
|
|
138
|
+
this._input = document.createElement('input');
|
|
139
|
+
this._input.type = this.inputType;
|
|
140
|
+
this._input.className = 'adw-check-input';
|
|
141
|
+
|
|
142
|
+
this._indicator = document.createElement('span');
|
|
143
|
+
this._indicator.className = 'adw-check-indicator';
|
|
144
|
+
|
|
145
|
+
this._label = document.createElement('span');
|
|
146
|
+
this._label.className = 'adw-check-label';
|
|
147
|
+
const authoredLabel = this.getAttribute('label');
|
|
148
|
+
if (authoredLabel === null) this._label.append(...authored);
|
|
149
|
+
else this._label.textContent = authoredLabel;
|
|
150
|
+
|
|
151
|
+
this.replaceChildren(this._input, this._indicator, this._label);
|
|
152
|
+
|
|
153
|
+
// Keyboard (Space, and the arrow keys that move within a radio group)
|
|
154
|
+
// and a direct programmatic `input.click()` both surface as `change`.
|
|
155
|
+
this._input.addEventListener('change', () => this.activate());
|
|
156
|
+
|
|
157
|
+
// The indicator and the label cover the control; the input is 0x0, so
|
|
158
|
+
// every pointer click lands on one of them. A click that DID reach the
|
|
159
|
+
// input is already handled above — activating again would undo it.
|
|
160
|
+
this.addEventListener('click', (event) => {
|
|
161
|
+
if (this.disabled) return;
|
|
162
|
+
if (event.target === this._input) return;
|
|
163
|
+
this.activate();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
this.onConnected();
|
|
167
|
+
this.render();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
disconnectedCallback() {
|
|
171
|
+
this.onDisconnected();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
attributeChangedCallback(name: string) {
|
|
175
|
+
if (!this._initialized) return;
|
|
176
|
+
if (name === 'label') {
|
|
177
|
+
this._label.textContent = this.getAttribute('label') ?? '';
|
|
178
|
+
}
|
|
179
|
+
this.render();
|
|
180
|
+
if (name === 'checked') {
|
|
181
|
+
this.dispatchEvent(
|
|
182
|
+
new CustomEvent('notify::checked', { bubbles: true, detail: { checked: this.checked } }),
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Extra wiring for a subclass on connect. */
|
|
188
|
+
protected onConnected(): void {}
|
|
189
|
+
|
|
190
|
+
/** Extra teardown for a subclass on disconnect. */
|
|
191
|
+
protected onDisconnected(): void {}
|
|
192
|
+
|
|
193
|
+
protected render(): void {
|
|
194
|
+
const state = resolveCheckState(this.checked, this.indeterminate);
|
|
195
|
+
this._input.checked = state === 'checked';
|
|
196
|
+
this._input.indeterminate = state === 'indeterminate';
|
|
197
|
+
// Explicit, because HTML has a native mixed CHECKBOX (the property
|
|
198
|
+
// above) but no mixed radio — this is the one spelling that announces
|
|
199
|
+
// the third state for both.
|
|
200
|
+
this._input.setAttribute('aria-checked', state === 'indeterminate' ? 'mixed' : String(state === 'checked'));
|
|
201
|
+
this._input.disabled = this.disabled;
|
|
202
|
+
this._label.hidden = this._label.childNodes.length === 0;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** The Adwaita checkbox — `checkbutton > check` as a custom element. */
|
|
207
|
+
export class AdwCheckbox extends AdwCheckBase {
|
|
208
|
+
static get observedAttributes() {
|
|
209
|
+
return ['checked', 'indeterminate', 'disabled', 'label'];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
protected get inputType(): 'checkbox' {
|
|
213
|
+
return 'checkbox';
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
protected activate(): void {
|
|
217
|
+
// HTML's pre-click activation steps clear `indeterminate` before the
|
|
218
|
+
// toggle, so a user can always reach a definite state. That rule is the
|
|
219
|
+
// HTML spec's, not a reading of GtkCheckButton:inconsistent, whose
|
|
220
|
+
// behaviour is not verifiable in this tree.
|
|
221
|
+
this.indeterminate = false;
|
|
222
|
+
this.checked = !this.checked;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** The Adwaita radio — `checkbutton > radio`, exclusive within its `name`. */
|
|
227
|
+
export class AdwRadio extends AdwCheckBase {
|
|
228
|
+
private _unsubscribe: (() => void) | null = null;
|
|
229
|
+
|
|
230
|
+
static get observedAttributes() {
|
|
231
|
+
return ['checked', 'indeterminate', 'disabled', 'label', 'name', 'value'];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
protected get inputType(): 'radio' {
|
|
235
|
+
return 'radio';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** The group this member belongs to. */
|
|
239
|
+
get name(): string {
|
|
240
|
+
return this.getAttribute('name') ?? '';
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
set name(value: string) {
|
|
244
|
+
this.setAttribute('name', value);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* This member's value. Falls back to the label text so a group authored
|
|
249
|
+
* without values still has members the group state can tell apart.
|
|
250
|
+
*/
|
|
251
|
+
get value(): string {
|
|
252
|
+
return this.getAttribute('value') ?? this.label.trim();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
set value(value: string) {
|
|
256
|
+
this.setAttribute('value', value);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected activate(): void {
|
|
260
|
+
this.indeterminate = false;
|
|
261
|
+
// An UNNAMED radio is not in a group — HTML forms a radio button group
|
|
262
|
+
// only from a non-empty `name`, so a nameless one checks itself and
|
|
263
|
+
// never unchecks anything. Without this guard every nameless radio in
|
|
264
|
+
// the document would join one `''` group and fight over it.
|
|
265
|
+
if (this.name === '') {
|
|
266
|
+
this.checked = true;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// The pick goes through the shared state, never straight onto this
|
|
270
|
+
// element: the member that LOSES the selection is a different element
|
|
271
|
+
// and only the state knows which one it is.
|
|
272
|
+
radioGroups.select(this.name, this.value);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
protected onConnected(): void {
|
|
276
|
+
this._input.name = this.name;
|
|
277
|
+
if (this.name === '') return; // ungrouped — nothing to subscribe to
|
|
278
|
+
this._unsubscribe ??= radioGroups.subscribe((change) => {
|
|
279
|
+
if (change.name !== this.name) return;
|
|
280
|
+
this.checked = change.selected === this.value;
|
|
281
|
+
});
|
|
282
|
+
// A member declared checked seeds the group, so the first user pick
|
|
283
|
+
// knows what it is deselecting.
|
|
284
|
+
if (this.checked) radioGroups.select(this.name, this.value);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
protected onDisconnected(): void {
|
|
288
|
+
this._unsubscribe?.();
|
|
289
|
+
this._unsubscribe = null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
protected render(): void {
|
|
293
|
+
super.render();
|
|
294
|
+
this._input.name = this.name;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
customElements.define('adw-checkbox', AdwCheckbox);
|
|
299
|
+
customElements.define('adw-radio', AdwRadio);
|
|
@@ -1,27 +1,97 @@
|
|
|
1
|
-
// <adw-clamp> — Constrains its
|
|
2
|
-
// Attributes: maximum-size (px, default 600), tightening-threshold (
|
|
3
|
-
//
|
|
1
|
+
// <adw-clamp> — Constrains its children to a maximum width and centers them.
|
|
2
|
+
// Attributes: maximum-size (px, default 600), tightening-threshold (px, default 400).
|
|
3
|
+
//
|
|
4
|
+
// The clamp is NOT a `max-width`, which is what this element used to be. Adwaita
|
|
5
|
+
// eases the child from "all the available width" into the cap across a tightening
|
|
6
|
+
// region, and stamps a `small`/`medium`/`large` class on it — the arithmetic lives
|
|
7
|
+
// in `@gjsify/adwaita-core` (`clampAllocate`) so this element and the NativeScript
|
|
8
|
+
// widget produce the same width for the same viewport.
|
|
9
|
+
//
|
|
10
|
+
// The cap now sits on the CHILDREN, not on this element. The element has to keep
|
|
11
|
+
// reporting the AVAILABLE width — it is what the curve is evaluated against — and
|
|
12
|
+
// an element that caps itself reports the capped width back to its own
|
|
13
|
+
// ResizeObserver, which is a feedback loop, not a measurement.
|
|
14
|
+
//
|
|
15
|
+
// `childMin` is passed as 0 rather than measured. libadwaita's
|
|
16
|
+
// `lower = MAX (…, child_min)` says a child is never squeezed below its own
|
|
17
|
+
// minimum, and the browser already applies that rule at the other end: `min-width`
|
|
18
|
+
// wins over `max-width` (CSS 2.1 §10.4), so a child that declares a minimum keeps
|
|
19
|
+
// it whatever cap this element writes. A child that declares none has a minimum of
|
|
20
|
+
// 0, which is the value passed here — measuring `min-content` per child on every
|
|
21
|
+
// resize would cost a synchronous reflow to arrive at the same layout.
|
|
22
|
+
//
|
|
23
|
+
// Reference: refs/libadwaita/src/adw-clamp-layout.c (child_size_from_clamp, allocate)
|
|
4
24
|
// Reference: refs/adwaita-web/adwaita-web/docs/widgets/clamp.md
|
|
5
|
-
// Reference: refs/libadwaita (Adw.Clamp)
|
|
6
25
|
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
7
26
|
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
8
27
|
|
|
28
|
+
import { ADW_CLAMP_DEFAULTS, ADW_CLAMP_SIZE_CLASSES, clampAllocate, normalizeClampSize } from '@gjsify/adwaita-core';
|
|
29
|
+
|
|
9
30
|
export class AdwClamp extends HTMLElement {
|
|
31
|
+
private _resize: ResizeObserver | null = null;
|
|
32
|
+
private _mutations: MutationObserver | null = null;
|
|
33
|
+
|
|
10
34
|
static get observedAttributes() {
|
|
11
|
-
return ['maximum-size'];
|
|
35
|
+
return ['maximum-size', 'tightening-threshold'];
|
|
12
36
|
}
|
|
13
37
|
|
|
14
38
|
connectedCallback() {
|
|
15
|
-
|
|
39
|
+
// ResizeObserver delivers an initial observation on observe(), so the
|
|
40
|
+
// first allocation lands before paint without a separate seeding pass.
|
|
41
|
+
this._resize = new ResizeObserver(() => this._allocate());
|
|
42
|
+
this._resize.observe(this);
|
|
43
|
+
// Children appended AFTER connect are clamped too. Without this they
|
|
44
|
+
// would keep whatever width they came with — the same "evaluated once at
|
|
45
|
+
// connect time" bug the toolbar view's empty-bar handling still has.
|
|
46
|
+
this._mutations = new MutationObserver(() => this._allocate());
|
|
47
|
+
this._mutations.observe(this, { childList: true });
|
|
48
|
+
this._allocate();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
disconnectedCallback() {
|
|
52
|
+
this._resize?.disconnect();
|
|
53
|
+
this._resize = null;
|
|
54
|
+
this._mutations?.disconnect();
|
|
55
|
+
this._mutations = null;
|
|
16
56
|
}
|
|
17
57
|
|
|
18
58
|
attributeChangedCallback() {
|
|
19
|
-
this.
|
|
59
|
+
this._allocate();
|
|
20
60
|
}
|
|
21
61
|
|
|
22
|
-
private
|
|
23
|
-
const
|
|
24
|
-
|
|
62
|
+
private _allocate(): void {
|
|
63
|
+
const params = {
|
|
64
|
+
maximumSize: normalizeClampSize(this.getAttribute('maximum-size'), ADW_CLAMP_DEFAULTS.maximumSize),
|
|
65
|
+
tighteningThreshold: normalizeClampSize(
|
|
66
|
+
this.getAttribute('tightening-threshold'),
|
|
67
|
+
ADW_CLAMP_DEFAULTS.tighteningThreshold,
|
|
68
|
+
),
|
|
69
|
+
childMin: 0,
|
|
70
|
+
childNat: 0,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const available = this.clientWidth;
|
|
74
|
+
const children = Array.from(this.children) as HTMLElement[];
|
|
75
|
+
|
|
76
|
+
// No box yet (disconnected, or measured before the first layout). GTK's
|
|
77
|
+
// equivalent is `for_size = -1`, where the child reports its natural size
|
|
78
|
+
// rather than being squeezed to nothing — so leave the children alone
|
|
79
|
+
// instead of capping them at 0 and collapsing the page.
|
|
80
|
+
if (available <= 0) {
|
|
81
|
+
for (const child of children) {
|
|
82
|
+
child.style.maxWidth = '';
|
|
83
|
+
child.style.marginInline = '';
|
|
84
|
+
for (const cls of ADW_CLAMP_SIZE_CLASSES) child.classList.remove(cls);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const { childSize, sizeClass } = clampAllocate(available, params);
|
|
90
|
+
for (const child of children) {
|
|
91
|
+
child.style.maxWidth = `${childSize}px`;
|
|
92
|
+
child.style.marginInline = 'auto';
|
|
93
|
+
for (const cls of ADW_CLAMP_SIZE_CLASSES) child.classList.toggle(cls, cls === sizeClass);
|
|
94
|
+
}
|
|
25
95
|
}
|
|
26
96
|
}
|
|
27
97
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// title/subtitle text column added to match Adw.ComboRow; the selection state
|
|
18
18
|
// machine composed from @gjsify/adwaita-core.
|
|
19
19
|
|
|
20
|
-
import { ComboState } from '@gjsify/adwaita-core';
|
|
20
|
+
import { ComboState, deriveRowLabels, normalizeComboOptions } from '@gjsify/adwaita-core';
|
|
21
21
|
|
|
22
22
|
export class AdwComboRow extends HTMLElement {
|
|
23
23
|
private _select!: HTMLSelectElement;
|
|
@@ -46,8 +46,10 @@ export class AdwComboRow extends HTMLElement {
|
|
|
46
46
|
|
|
47
47
|
const items: string[] = JSON.parse(this.getAttribute('items') || '[]');
|
|
48
48
|
// Seed the headless state BEFORE subscribing, so building the initial DOM
|
|
49
|
-
// below is not driven by a change notification.
|
|
50
|
-
|
|
49
|
+
// below is not driven by a change notification. The string→descriptor
|
|
50
|
+
// mapping is core's: `<adw-drop-down>` had its own, richer copy, so the
|
|
51
|
+
// two selectors accepted different option vocabularies.
|
|
52
|
+
this._state.setOptions(normalizeComboOptions(items));
|
|
51
53
|
this._state.setSelectedIndex(parseInt(this.getAttribute('selected') || '0', 10));
|
|
52
54
|
const selectedIdx = this._state.selectedIndex;
|
|
53
55
|
|
|
@@ -114,10 +116,16 @@ export class AdwComboRow extends HTMLElement {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
private _renderText() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
// The `string_is_not_empty` label rule, from core — this block was one of
|
|
120
|
+
// six hand-rolled copies, all of which omitted the TITLE half.
|
|
121
|
+
const labels = deriveRowLabels({
|
|
122
|
+
title: this.getAttribute('title'),
|
|
123
|
+
subtitle: this.getAttribute('subtitle'),
|
|
124
|
+
});
|
|
125
|
+
this._titleEl.textContent = labels.title;
|
|
126
|
+
this._titleEl.hidden = !labels.titleVisible;
|
|
127
|
+
this._subtitleEl.textContent = labels.subtitle;
|
|
128
|
+
this._subtitleEl.hidden = !labels.subtitleVisible;
|
|
121
129
|
}
|
|
122
130
|
}
|
|
123
131
|
|
|
@@ -51,46 +51,36 @@
|
|
|
51
51
|
// Responsive: the grid scrolls horizontally within its OWN container on narrow
|
|
52
52
|
// viewports (it never overflows the page); it sits inside an <adw-card>/boxed
|
|
53
53
|
// surface and follows light + dark via the adwaita-web CSS variables.
|
|
54
|
+
// The derivations are HEADLESS and live in `@gjsify/adwaita-core` (ADR 0004):
|
|
55
|
+
// the column tracks, the cell classes, the two normalisers, the cell text and
|
|
56
|
+
// the activation rule. `@gjsify/adwaita-nativescript` renders the same widget
|
|
57
|
+
// over `GridLayout` `ItemSpec`s — NativeScript has no subgrid — so the TRACK
|
|
58
|
+
// rule is emitted as a renderer-neutral descriptor and only the mapping onto
|
|
59
|
+
// `grid-template-columns` stays here. `@gjsify/adwaita-core/conformance`'s
|
|
60
|
+
// `DATA_GRID_*_VECTORS` is the table both ports are held to.
|
|
54
61
|
// Reference: Gtk.Grid usage in the Buchhaltung BWA view (native financial grid).
|
|
55
62
|
// Reference: refs/libadwaita/src/stylesheet/_colors.scss (separator / card tokens).
|
|
56
63
|
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
57
64
|
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
/** Render cells in a monospace family (tabular figures apply regardless). */
|
|
78
|
-
monospace?: boolean;
|
|
79
|
-
/** Convenience: right-align + tabular-nums (numeric columns of figures). */
|
|
80
|
-
numeric?: boolean;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** A row: cell values keyed by column key + optional accounting metadata. */
|
|
84
|
-
export interface AdwDataGridRow {
|
|
85
|
-
/** Accounting emphasis. Default 'normal'. */
|
|
86
|
-
variant?: AdwDataGridRowVariant;
|
|
87
|
-
/** Make just this row clickable (overrides the element-level flag). */
|
|
88
|
-
interactive?: boolean;
|
|
89
|
-
/** Cell values keyed by column key (pre-formatted strings, or numbers). */
|
|
90
|
-
[key: string]: string | number | boolean | AdwDataGridRowVariant | undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const VARIANTS: ReadonlySet<string> = new Set(['normal', 'section', 'subtotal', 'total']);
|
|
66
|
+
import {
|
|
67
|
+
dataGridCellText,
|
|
68
|
+
dataGridColumnClasses,
|
|
69
|
+
dataGridRowInteractive,
|
|
70
|
+
dataGridTrackTemplate,
|
|
71
|
+
dataGridTracks,
|
|
72
|
+
normalizeDataGridColumns,
|
|
73
|
+
normalizeDataGridVariant,
|
|
74
|
+
} from '@gjsify/adwaita-core';
|
|
75
|
+
import type { AdwDataGridColumn, AdwDataGridRow } from '@gjsify/adwaita-core';
|
|
76
|
+
|
|
77
|
+
export type {
|
|
78
|
+
AdwDataGridAlign,
|
|
79
|
+
AdwDataGridCellValue,
|
|
80
|
+
AdwDataGridColumn,
|
|
81
|
+
AdwDataGridRow,
|
|
82
|
+
AdwDataGridRowVariant,
|
|
83
|
+
} from '@gjsify/adwaita-core';
|
|
94
84
|
|
|
95
85
|
export class AdwDataGrid extends HTMLElement {
|
|
96
86
|
private _captionEl!: HTMLDivElement;
|
|
@@ -110,7 +100,7 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
110
100
|
}
|
|
111
101
|
|
|
112
102
|
set columns(value: ReadonlyArray<AdwDataGridColumn>) {
|
|
113
|
-
this._columns =
|
|
103
|
+
this._columns = normalizeDataGridColumns(value);
|
|
114
104
|
if (this._initialized) this._render();
|
|
115
105
|
}
|
|
116
106
|
|
|
@@ -163,7 +153,7 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
163
153
|
this._scrollEl.appendChild(this._tableEl);
|
|
164
154
|
|
|
165
155
|
// Seed from JSON attributes only when the properties were not set.
|
|
166
|
-
if (this._columns.length === 0) this._columns = this._parseJsonAttr('columns',
|
|
156
|
+
if (this._columns.length === 0) this._columns = this._parseJsonAttr('columns', normalizeDataGridColumns);
|
|
167
157
|
if (this._rows.length === 0) this._rows = this._parseJsonAttr('rows', (v) => (Array.isArray(v) ? v : []));
|
|
168
158
|
|
|
169
159
|
this.replaceChildren(this._captionEl, this._scrollEl);
|
|
@@ -173,7 +163,7 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
173
163
|
attributeChangedCallback(name: string, _old: string | null, value: string | null) {
|
|
174
164
|
if (!this._initialized) return;
|
|
175
165
|
if (name === 'columns') {
|
|
176
|
-
this._columns = this._parseJsonAttr('columns',
|
|
166
|
+
this._columns = this._parseJsonAttr('columns', normalizeDataGridColumns);
|
|
177
167
|
this._render();
|
|
178
168
|
} else if (name === 'rows') {
|
|
179
169
|
this._rows = this._parseJsonAttr('rows', (v) => (Array.isArray(v) ? (v as AdwDataGridRow[]) : []));
|
|
@@ -204,28 +194,21 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
204
194
|
this._captionEl.hidden = caption.length === 0;
|
|
205
195
|
}
|
|
206
196
|
|
|
207
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* The CSS `grid-template-columns` value derived from the column descriptors.
|
|
199
|
+
*
|
|
200
|
+
* The DERIVATION is core's (`dataGridTracks`), because NativeScript needs the
|
|
201
|
+
* same one for its `ItemSpec`s and can do nothing with a CSS string; the
|
|
202
|
+
* mapping onto CSS text — including the `minmax(0px, 1fr)` slack track whose
|
|
203
|
+
* `0px` must keep its unit to round-trip through the CSSOM — is
|
|
204
|
+
* `dataGridTrackTemplate`.
|
|
205
|
+
*/
|
|
208
206
|
private _trackTemplate(): string {
|
|
209
|
-
|
|
210
|
-
return this._columns
|
|
211
|
-
.map((column, index) => {
|
|
212
|
-
if (column.width !== undefined) return column.width;
|
|
213
|
-
if (column.flex !== undefined) return `${column.flex}fr`;
|
|
214
|
-
// With no explicit sizing anywhere, the first (label) column
|
|
215
|
-
// absorbs slack so trailing numeric columns hug the right edge.
|
|
216
|
-
// `0px` (not `0`) is the CSSOM-canonical form so it round-trips.
|
|
217
|
-
if (!anyExplicit && index === 0) return 'minmax(0px, 1fr)';
|
|
218
|
-
return 'auto';
|
|
219
|
-
})
|
|
220
|
-
.join(' ');
|
|
207
|
+
return dataGridTrackTemplate(dataGridTracks(this._columns));
|
|
221
208
|
}
|
|
222
209
|
|
|
223
210
|
private _columnClasses(column: AdwDataGridColumn): string {
|
|
224
|
-
|
|
225
|
-
const classes = ['adw-data-grid-cell', `align-${align}`];
|
|
226
|
-
if (column.numeric) classes.push('numeric');
|
|
227
|
-
if (column.monospace) classes.push('mono');
|
|
228
|
-
return classes.join(' ');
|
|
211
|
+
return dataGridColumnClasses(column).join(' ');
|
|
229
212
|
}
|
|
230
213
|
|
|
231
214
|
private _render(): void {
|
|
@@ -253,7 +236,7 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
253
236
|
const elementInteractive = this.hasAttribute('interactive');
|
|
254
237
|
|
|
255
238
|
this._rows.forEach((rowData, index) => {
|
|
256
|
-
const variant =
|
|
239
|
+
const variant = normalizeDataGridVariant(rowData.variant);
|
|
257
240
|
const row = document.createElement('div');
|
|
258
241
|
row.className = `adw-data-grid-row variant-${variant}`;
|
|
259
242
|
row.setAttribute('role', 'row');
|
|
@@ -266,25 +249,21 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
266
249
|
cell.className = 'adw-data-grid-cell align-start section-cell';
|
|
267
250
|
cell.setAttribute('role', 'cell');
|
|
268
251
|
cell.style.gridColumn = '1 / -1';
|
|
269
|
-
cell.textContent =
|
|
252
|
+
cell.textContent = dataGridCellText(rowData[firstKey]);
|
|
270
253
|
row.appendChild(cell);
|
|
271
254
|
} else {
|
|
272
255
|
for (const column of this._columns) {
|
|
273
256
|
const cell = document.createElement('div');
|
|
274
257
|
cell.className = this._columnClasses(column);
|
|
275
258
|
cell.setAttribute('role', 'cell');
|
|
276
|
-
cell.textContent =
|
|
259
|
+
cell.textContent = dataGridCellText(rowData[column.key]);
|
|
277
260
|
row.appendChild(cell);
|
|
278
261
|
}
|
|
279
262
|
}
|
|
280
263
|
|
|
281
264
|
// A row is clickable only when it is a plain data row AND either the
|
|
282
265
|
// element opts everything in or the row opts itself in.
|
|
283
|
-
|
|
284
|
-
variant === 'normal' &&
|
|
285
|
-
rowData.interactive !== false &&
|
|
286
|
-
(rowData.interactive === true || elementInteractive);
|
|
287
|
-
if (rowInteractive) {
|
|
266
|
+
if (dataGridRowInteractive(variant, rowData.interactive, elementInteractive)) {
|
|
288
267
|
row.classList.add('interactive');
|
|
289
268
|
row.tabIndex = 0;
|
|
290
269
|
row.addEventListener('click', () => this._activate(index, rowData));
|
|
@@ -305,31 +284,4 @@ export class AdwDataGrid extends HTMLElement {
|
|
|
305
284
|
}
|
|
306
285
|
}
|
|
307
286
|
|
|
308
|
-
/** Coerce a cell value to display text — pre-formatted strings pass through. */
|
|
309
|
-
function cellText(value: string | number | boolean | AdwDataGridRowVariant | undefined): string {
|
|
310
|
-
if (value === undefined || value === null) return '';
|
|
311
|
-
return String(value);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/** Clamp an arbitrary variant to the known set (unknown → 'normal'). */
|
|
315
|
-
function normalizeVariant(variant: unknown): AdwDataGridRowVariant {
|
|
316
|
-
return typeof variant === 'string' && VARIANTS.has(variant) ? (variant as AdwDataGridRowVariant) : 'normal';
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/** Normalise raw column descriptors to a stable list (drops malformed entries). */
|
|
320
|
-
function normalizeColumns(raw: unknown): AdwDataGridColumn[] {
|
|
321
|
-
if (!Array.isArray(raw)) return [];
|
|
322
|
-
return raw
|
|
323
|
-
.filter((c): c is AdwDataGridColumn => typeof c === 'object' && c !== null && 'key' in c)
|
|
324
|
-
.map((c) => ({
|
|
325
|
-
key: String(c.key),
|
|
326
|
-
label: c.label !== undefined ? String(c.label) : undefined,
|
|
327
|
-
align: c.align,
|
|
328
|
-
width: c.width !== undefined ? String(c.width) : undefined,
|
|
329
|
-
flex: typeof c.flex === 'number' ? c.flex : undefined,
|
|
330
|
-
monospace: c.monospace === true,
|
|
331
|
-
numeric: c.numeric === true,
|
|
332
|
-
}));
|
|
333
|
-
}
|
|
334
|
-
|
|
335
287
|
customElements.define('adw-data-grid', AdwDataGrid);
|