@gjsify/adwaita-web 0.35.0 → 0.37.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 +433 -33
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-shortcut-label.spec.d.ts +2 -0
- package/lib/types/breakpoints.d.ts +10 -12
- package/lib/types/elements/adw-about-dialog.d.ts +19 -36
- package/lib/types/elements/adw-action-row.d.ts +9 -12
- package/lib/types/elements/adw-alert-dialog.d.ts +0 -12
- package/lib/types/elements/adw-avatar.d.ts +1 -0
- package/lib/types/elements/adw-bottom-sheet.d.ts +7 -12
- package/lib/types/elements/adw-button-content.d.ts +3 -4
- package/lib/types/elements/adw-button-row.d.ts +1 -1
- package/lib/types/elements/adw-carousel.d.ts +28 -49
- package/lib/types/elements/adw-checks.d.ts +2 -8
- package/lib/types/elements/adw-combo-row.d.ts +6 -6
- package/lib/types/elements/adw-data-grid.d.ts +5 -10
- package/lib/types/elements/adw-drop-down.d.ts +3 -11
- package/lib/types/elements/adw-entry-row.d.ts +20 -23
- package/lib/types/elements/adw-icon.d.ts +2 -4
- package/lib/types/elements/adw-inline-view-switcher.d.ts +18 -31
- package/lib/types/elements/adw-navigation-split-view.d.ts +7 -12
- package/lib/types/elements/adw-navigation-view.d.ts +2 -10
- package/lib/types/elements/adw-overlay-split-view.d.ts +28 -52
- package/lib/types/elements/adw-password-entry-row.d.ts +4 -5
- package/lib/types/elements/adw-popover.d.ts +2 -7
- package/lib/types/elements/adw-preferences-dialog.d.ts +21 -34
- package/lib/types/elements/adw-preferences-group.d.ts +12 -14
- package/lib/types/elements/adw-progress-bar.d.ts +3 -4
- package/lib/types/elements/adw-shortcut-label.d.ts +20 -0
- package/lib/types/elements/adw-sidebar.d.ts +5 -10
- package/lib/types/elements/adw-spinner.d.ts +3 -5
- package/lib/types/elements/adw-split-button.d.ts +6 -16
- package/lib/types/elements/adw-switch-row.d.ts +3 -3
- package/lib/types/elements/adw-tab-view.d.ts +16 -26
- package/lib/types/elements/adw-toast-overlay.d.ts +8 -13
- package/lib/types/elements/adw-view-stack.d.ts +7 -17
- package/lib/types/elements/adw-view-switcher-bar.d.ts +4 -8
- package/lib/types/elements/adw-view-switcher.d.ts +18 -38
- package/lib/types/elements/adw-wrap-box.d.ts +7 -17
- package/lib/types/elements/view-switcher-dom.d.ts +10 -13
- package/lib/types/index.d.ts +1 -0
- package/lib/types/source-view/hex.d.ts +7 -13
- package/lib/types/style-classes.spec.d.ts +11 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/package.json +6 -6
- package/scss/_about_dialog.scss +3 -2
- package/scss/_action_row.scss +33 -0
- package/scss/_avatar.scss +12 -0
- package/scss/_button.scss +44 -22
- package/scss/_card.scss +11 -8
- package/scss/_checks.scss +2 -4
- package/scss/_dialog.scss +3 -2
- package/scss/_headerbar.scss +23 -0
- package/scss/_popover.scss +8 -4
- package/scss/_preferences.scss +7 -7
- package/scss/_progress_bar.scss +9 -6
- package/scss/_reset.scss +1 -1
- package/scss/_shortcut_label.scss +80 -0
- package/scss/_sidebar.scss +57 -0
- package/scss/_status_page.scss +20 -0
- package/scss/_style_classes.scss +407 -0
- package/scss/_switch.scss +4 -3
- package/scss/_variables.scss +25 -0
- package/scss/adwaita-skin.scss +12 -0
- package/src/adw-about-dialog.spec.ts +34 -49
- package/src/adw-action-rows.spec.ts +25 -33
- package/src/adw-avatar.spec.ts +51 -20
- package/src/adw-banner.spec.ts +5 -8
- package/src/adw-button-content.spec.ts +9 -12
- package/src/adw-button-row.spec.ts +2 -4
- package/src/adw-carousel.spec.ts +40 -53
- package/src/adw-checks.spec.ts +36 -47
- package/src/adw-drop-down.spec.ts +25 -32
- package/src/adw-header-bar.spec.ts +5 -7
- package/src/adw-icon.spec.ts +23 -32
- package/src/adw-progress-bar.spec.ts +10 -12
- package/src/adw-row-state.spec.ts +9 -10
- package/src/adw-shortcut-label.spec.ts +112 -0
- package/src/adw-sidebar.spec.ts +17 -24
- package/src/adw-switch.spec.ts +11 -17
- package/src/adw-tab-view.spec.ts +7 -10
- package/src/adw-toast-overlay.spec.ts +7 -11
- package/src/adw-view-switcher-bar.spec.ts +10 -14
- package/src/adw-wrap-box.spec.ts +25 -36
- package/src/bottom-sheet.spec.ts +30 -36
- package/src/breakpoints.ts +15 -18
- package/src/chrome.spec.ts +13 -21
- package/src/elements/adw-about-dialog.ts +71 -114
- package/src/elements/adw-action-row.ts +22 -37
- package/src/elements/adw-alert-dialog.ts +25 -50
- package/src/elements/adw-avatar.ts +40 -15
- package/src/elements/adw-banner.ts +14 -18
- package/src/elements/adw-bottom-sheet.ts +31 -52
- package/src/elements/adw-button-content.ts +30 -37
- package/src/elements/adw-button-row.ts +14 -24
- package/src/elements/adw-carousel.ts +87 -148
- package/src/elements/adw-checks.ts +43 -56
- package/src/elements/adw-clamp.ts +8 -9
- package/src/elements/adw-combo-row.ts +17 -25
- package/src/elements/adw-data-grid.ts +26 -38
- package/src/elements/adw-dialog.ts +25 -56
- package/src/elements/adw-drop-down.ts +31 -51
- package/src/elements/adw-entry-row.ts +39 -46
- package/src/elements/adw-expander-row.ts +30 -53
- package/src/elements/adw-icon.ts +30 -53
- package/src/elements/adw-inline-view-switcher.ts +38 -67
- package/src/elements/adw-menu-button.ts +28 -58
- package/src/elements/adw-navigation-split-view.ts +35 -47
- package/src/elements/adw-navigation-view.ts +12 -28
- package/src/elements/adw-overlay-split-view.ts +100 -175
- package/src/elements/adw-password-entry-row.ts +18 -28
- package/src/elements/adw-popover.ts +28 -44
- package/src/elements/adw-preferences-dialog.ts +41 -66
- package/src/elements/adw-preferences-group.ts +33 -46
- package/src/elements/adw-progress-bar.ts +27 -47
- package/src/elements/adw-shortcut-label.ts +138 -0
- package/src/elements/adw-sidebar.ts +31 -39
- package/src/elements/adw-spin-row.ts +7 -14
- package/src/elements/adw-spinner.ts +31 -43
- package/src/elements/adw-split-button.ts +45 -75
- package/src/elements/adw-switch-row.ts +29 -46
- package/src/elements/adw-switch.ts +28 -47
- package/src/elements/adw-tab-view.ts +62 -103
- package/src/elements/adw-toast-overlay.ts +28 -35
- package/src/elements/adw-toggle-group.ts +9 -16
- package/src/elements/adw-view-stack.ts +32 -51
- package/src/elements/adw-view-switcher-bar.ts +26 -50
- package/src/elements/adw-view-switcher.ts +60 -110
- package/src/elements/adw-window-title.ts +4 -4
- package/src/elements/adw-wrap-box.ts +33 -59
- package/src/elements/view-switcher-dom.ts +15 -22
- package/src/entry-rows.spec.ts +18 -24
- package/src/index.ts +13 -15
- package/src/navigation-view.spec.ts +7 -10
- package/src/preferences-search.ts +11 -15
- package/src/preferences.spec.ts +13 -15
- package/src/source-view/adw-source-view.ts +6 -19
- package/src/source-view/hex.ts +7 -13
- package/src/split-button.spec.ts +32 -44
- package/src/split-views.spec.ts +83 -149
- package/src/style-classes.spec.ts +181 -0
- package/src/style-isolation.spec.ts +3 -6
- package/src/styles.generated.ts +1 -1
- package/src/tab-view.spec.ts +26 -35
- package/src/test.browser.mts +4 -0
- package/src/view-stack.spec.ts +23 -34
- package/src/view-switcher.spec.ts +56 -84
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
// `flex-wrap: wrap` with a gap). Mirrors Adw.WrapBox.
|
|
4
4
|
//
|
|
5
5
|
// Attributes — all fourteen of the widget's properties, each with a
|
|
6
|
-
// `notify::<property
|
|
7
|
-
// attributes and notify for two, so a consumer binding to any of the other
|
|
8
|
-
// twelve was listening to a signal that could not fire.
|
|
6
|
+
// `notify::<property>`:
|
|
9
7
|
//
|
|
10
8
|
// child-spacing / line-spacing (int >= 0, default 0) -> column-gap / row-gap
|
|
11
9
|
// child-spacing-unit / line-spacing-unit ("px" | "pt" | "sp", default "px")
|
|
@@ -19,10 +17,9 @@
|
|
|
19
17
|
// wrap-policy ("minimum" | "natural", default "natural")
|
|
20
18
|
// natural-line-length (int >= -1, default -1 = unset) + -unit
|
|
21
19
|
//
|
|
22
|
-
// The property CONTRACT — the normalisers and the justify/align/last-line
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
// This element used to carry its own copy of all of it.
|
|
20
|
+
// The property CONTRACT — the normalisers and the justify/align/last-line decision —
|
|
21
|
+
// is `@gjsify/adwaita-core`'s `wrap-box.ts`, held to `WRAP_BOX_LINE_VECTORS` and
|
|
22
|
+
// friends, which the NativeScript suite drives too.
|
|
26
23
|
//
|
|
27
24
|
// Reference: refs/libadwaita/src/adw-wrap-box.c / adw-wrap-layout.c (Adw.WrapBox)
|
|
28
25
|
// Reference: refs/adwaita-web/adwaita-web/scss/_wrap_box.scss
|
|
@@ -72,12 +69,10 @@ const PROPERTY_ATTRIBUTES = [
|
|
|
72
69
|
type PropertyValue = string | number | boolean;
|
|
73
70
|
|
|
74
71
|
/**
|
|
75
|
-
* `align` as a `justify-content` keyword.
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* that is the renderer's approximation, not libadwaita's rule, which is why it
|
|
80
|
-
* lives here and not in the conformance table.
|
|
72
|
+
* `align` as a `justify-content` keyword. C offsets the whole line block by
|
|
73
|
+
* `roundf (length_delta * align)` — a continuum — while flexbox has three main-axis
|
|
74
|
+
* positions, so the nearest one is taken. That approximation is the renderer's, not
|
|
75
|
+
* libadwaita's rule, which is why it lives here and not in the conformance table.
|
|
81
76
|
*/
|
|
82
77
|
function alignToJustifyContent(align: number): string {
|
|
83
78
|
if (align < 0.25) return 'flex-start';
|
|
@@ -92,8 +87,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
92
87
|
return [...PROPERTY_ATTRIBUTES];
|
|
93
88
|
}
|
|
94
89
|
|
|
95
|
-
// --- properties ---
|
|
96
|
-
|
|
97
90
|
/** Spacing between children on the same line, in `child-spacing-unit`. */
|
|
98
91
|
get childSpacing(): number {
|
|
99
92
|
return normalizeWrapBoxSpacing(this.getAttribute('child-spacing'));
|
|
@@ -103,7 +96,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
103
96
|
this.setAttribute('child-spacing', String(value));
|
|
104
97
|
}
|
|
105
98
|
|
|
106
|
-
/** The unit `child-spacing` is written in. Defaults to `px`, as in C. */
|
|
107
99
|
get childSpacingUnit(): AdwLengthUnit {
|
|
108
100
|
return normalizeWrapBoxLengthUnit(this.getAttribute('child-spacing-unit'));
|
|
109
101
|
}
|
|
@@ -121,7 +113,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
121
113
|
this.setAttribute('line-spacing', String(value));
|
|
122
114
|
}
|
|
123
115
|
|
|
124
|
-
/** The unit `line-spacing` is written in. Defaults to `px`, as in C. */
|
|
125
116
|
get lineSpacingUnit(): AdwLengthUnit {
|
|
126
117
|
return normalizeWrapBoxLengthUnit(this.getAttribute('line-spacing-unit'));
|
|
127
118
|
}
|
|
@@ -139,7 +130,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
139
130
|
this.setAttribute('align', String(value));
|
|
140
131
|
}
|
|
141
132
|
|
|
142
|
-
/** Whether and how each line is stretched to fill the widget. */
|
|
143
133
|
get justify(): 'none' | 'fill' | 'spread' {
|
|
144
134
|
return normalizeWrapBoxJustify(this.getAttribute('justify'));
|
|
145
135
|
}
|
|
@@ -166,7 +156,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
166
156
|
this.setAttribute('wrap-policy', value);
|
|
167
157
|
}
|
|
168
158
|
|
|
169
|
-
/** The direction children are packed in each line. */
|
|
170
159
|
get packDirection(): 'start-to-end' | 'end-to-start' {
|
|
171
160
|
return normalizeWrapBoxPackDirection(this.getAttribute('pack-direction'));
|
|
172
161
|
}
|
|
@@ -184,7 +173,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
184
173
|
this.toggleAttribute('wrap-reverse', !!value);
|
|
185
174
|
}
|
|
186
175
|
|
|
187
|
-
/** Whether every line takes the same amount of space. */
|
|
188
176
|
get lineHomogeneous(): boolean {
|
|
189
177
|
return this.hasAttribute('line-homogeneous');
|
|
190
178
|
}
|
|
@@ -202,7 +190,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
202
190
|
this.setAttribute('natural-line-length', String(value));
|
|
203
191
|
}
|
|
204
192
|
|
|
205
|
-
/** The unit `natural-line-length` is written in. Defaults to `px`, as in C. */
|
|
206
193
|
get naturalLineLengthUnit(): AdwLengthUnit {
|
|
207
194
|
return normalizeWrapBoxLengthUnit(this.getAttribute('natural-line-length-unit'));
|
|
208
195
|
}
|
|
@@ -211,7 +198,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
211
198
|
this.setAttribute('natural-line-length-unit', value);
|
|
212
199
|
}
|
|
213
200
|
|
|
214
|
-
/** The axis children are packed along. */
|
|
215
201
|
get orientation(): 'horizontal' | 'vertical' {
|
|
216
202
|
return this.getAttribute('orientation') === 'vertical' ? 'vertical' : 'horizontal';
|
|
217
203
|
}
|
|
@@ -220,37 +206,31 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
220
206
|
this.setAttribute('orientation', value);
|
|
221
207
|
}
|
|
222
208
|
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
// those three, with the same semantics, and shadowing them would give this
|
|
228
|
-
// element two spellings of one operation. Only the three the DOM has no
|
|
229
|
-
// counterpart for are added.
|
|
209
|
+
// `adw_wrap_box_append`, `_prepend` and `_remove` are deliberately NOT redeclared:
|
|
210
|
+
// `ParentNode.append` / `.prepend` and `Node.removeChild` ARE those three, with the
|
|
211
|
+
// same semantics, and shadowing them would give this element two spellings of one
|
|
212
|
+
// operation. Only the three the DOM has no counterpart for are added.
|
|
230
213
|
|
|
231
|
-
/** The element children, which are what the layout actually lays out. */
|
|
232
214
|
private get _children(): Element[] {
|
|
233
215
|
return [...this.children];
|
|
234
216
|
}
|
|
235
217
|
|
|
236
218
|
/**
|
|
237
|
-
* `adw_wrap_box_insert_child_after`
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* `WRAP_BOX_CHILD_ORDER_VECTORS`. Returns whether the insert happened; a
|
|
242
|
-
* refusal is where C would have hit a `g_return_if_fail`.
|
|
219
|
+
* `adw_wrap_box_insert_child_after`. A NULL/absent `sibling` inserts at the FIRST
|
|
220
|
+
* position, not the last — `gtk_widget_insert_after`'s documented rule, pinned by
|
|
221
|
+
* `WRAP_BOX_CHILD_ORDER_VECTORS`. Returns whether the insert happened; a refusal is
|
|
222
|
+
* where C would have hit a `g_return_if_fail`.
|
|
243
223
|
*/
|
|
244
224
|
insertChildAfter(child: Element, sibling: Element | null = null): boolean {
|
|
245
225
|
return this._applyOrder('insert-after', child, sibling);
|
|
246
226
|
}
|
|
247
227
|
|
|
248
|
-
/** `adw_wrap_box_reorder_child_after
|
|
228
|
+
/** `adw_wrap_box_reorder_child_after`. Same NULL rule. */
|
|
249
229
|
reorderChildAfter(child: Element, sibling: Element | null = null): boolean {
|
|
250
230
|
return this._applyOrder('reorder-after', child, sibling);
|
|
251
231
|
}
|
|
252
232
|
|
|
253
|
-
/** `adw_wrap_box_remove_all
|
|
233
|
+
/** `adw_wrap_box_remove_all`. */
|
|
254
234
|
removeAll(): void {
|
|
255
235
|
for (const child of this._children) this.removeChild(child);
|
|
256
236
|
}
|
|
@@ -267,8 +247,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
267
247
|
return true;
|
|
268
248
|
}
|
|
269
249
|
|
|
270
|
-
// --- lifecycle ---
|
|
271
|
-
|
|
272
250
|
connectedCallback() {
|
|
273
251
|
if (this._initialized) return;
|
|
274
252
|
this._initialized = true;
|
|
@@ -278,10 +256,9 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
278
256
|
attributeChangedCallback(name: string, old: string | null, value: string | null) {
|
|
279
257
|
if (!this._initialized) return;
|
|
280
258
|
this._sync();
|
|
281
|
-
// C compares AFTER normalising and returns early when nothing changed
|
|
282
|
-
//
|
|
283
|
-
//
|
|
284
|
-
// two spacings this element used to special-case.
|
|
259
|
+
// C compares AFTER normalising and returns early when nothing changed, so
|
|
260
|
+
// `child-spacing="-5"` on a box already at 0 notifies nobody. The gate applies to
|
|
261
|
+
// EVERY property, not just the two spacings.
|
|
285
262
|
const next = this._normalized(name, value);
|
|
286
263
|
if (next === this._normalized(name, old)) return;
|
|
287
264
|
this.dispatchEvent(new CustomEvent(`notify::${name}`, { bubbles: true, detail: { [name]: next } }));
|
|
@@ -319,7 +296,6 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
319
296
|
const style = this.style;
|
|
320
297
|
const vertical = this.orientation === 'vertical';
|
|
321
298
|
|
|
322
|
-
// Main axis is the packing direction; lines wrap along the cross axis.
|
|
323
299
|
const direction = vertical ? 'column' : 'row';
|
|
324
300
|
style.flexDirection = this.packDirection === 'end-to-start' ? `${direction}-reverse` : direction;
|
|
325
301
|
style.flexWrap = this.wrapReverse ? 'wrap-reverse' : 'wrap';
|
|
@@ -345,14 +321,13 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
345
321
|
const justifyLastLine = this.justifyLastLine;
|
|
346
322
|
const align = this.align;
|
|
347
323
|
|
|
348
|
-
// A flex container has ONE `justify-content` and applies it to every
|
|
349
|
-
//
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
// what made `justify-last-line` a no-op in the first place.
|
|
324
|
+
// A flex container has ONE `justify-content` and applies it to every line, so it
|
|
325
|
+
// carries the COMPLETE-line rule; the final-line rule is published beside it for
|
|
326
|
+
// the stylesheet, which reaches that line through the only two selectors CSS
|
|
327
|
+
// offers — `:only-child` (a box with one child has one line, and it is the last)
|
|
328
|
+
// and the generated `::after` filler. Never collapse the pair into one attribute:
|
|
329
|
+
// flexbox cannot express "every line but the last", and pretending it can is what
|
|
330
|
+
// makes `justify-last-line` a no-op.
|
|
356
331
|
const line = resolveWrapBoxLine({ justify, justifyLastLine, align, lastLine: false, childrenInLine: 2 });
|
|
357
332
|
const lastLine = resolveWrapBoxLine({ justify, justifyLastLine, align, lastLine: true, childrenInLine: 2 });
|
|
358
333
|
this.dataset.lineJustify = line.justify;
|
|
@@ -367,12 +342,11 @@ export class AdwWrapBox extends HTMLElement {
|
|
|
367
342
|
// flexbox approximates by stretching the lines across the cross axis.
|
|
368
343
|
style.alignContent = this.lineHomogeneous ? 'stretch' : 'flex-start';
|
|
369
344
|
|
|
370
|
-
// `wrap-policy` decides whether an overflowing line squeezes its children
|
|
371
|
-
//
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
// line breaking runs on hypothetical sizes; see `wrapPolicyFlexShrink`.
|
|
345
|
+
// `wrap-policy` decides whether an overflowing line squeezes its children or lets
|
|
346
|
+
// them spill. CSS defaults `flex-shrink` to 1, i.e. to ADW_WRAP_MINIMUM — which is
|
|
347
|
+
// NOT libadwaita's default, so the policy has to be written out explicitly. What
|
|
348
|
+
// flexbox cannot do either way is pack MORE children onto a line, since line
|
|
349
|
+
// breaking runs on hypothetical sizes; see `wrapPolicyFlexShrink`.
|
|
376
350
|
style.setProperty('--adw-wrap-box-child-shrink', String(wrapPolicyFlexShrink(this.wrapPolicy)));
|
|
377
351
|
|
|
378
352
|
// DELIBERATE DEVIATION: libadwaita's `natural-line-length` caps the box's
|
|
@@ -9,11 +9,8 @@
|
|
|
9
9
|
// NAME turned into a CSS mask class, an indicator span, and a `setTimeout`
|
|
10
10
|
// wrapped in the scheduler seam the core takes for the drag-hover dwell.
|
|
11
11
|
//
|
|
12
|
-
// Shared by
|
|
13
|
-
// `<adw-view-switcher>`,
|
|
14
|
-
// `<adw-view-switcher-bar>` each built their own icon span and their own page
|
|
15
|
-
// parsing, and the copies had already drifted (a titleless page rendered `''` in
|
|
16
|
-
// one and `page-<index>` in another).
|
|
12
|
+
// Shared by `<adw-view-switcher>`, `<adw-inline-view-switcher>` and
|
|
13
|
+
// `<adw-view-switcher-bar>`, so their icon nodes and page parsing cannot drift apart.
|
|
17
14
|
//
|
|
18
15
|
// Reference: refs/libadwaita/src/adw-view-switcher.c
|
|
19
16
|
// Reference: refs/libadwaita/src/adw-indicator-bin.c
|
|
@@ -26,11 +23,9 @@ import type { AdwViewSwitcherPageInit, ViewSwitcherScheduler, ViewSwitcherTimerH
|
|
|
26
23
|
import { type AdwIcon, createAdwIcon } from './adw-icon.js';
|
|
27
24
|
|
|
28
25
|
/**
|
|
29
|
-
* The browser's timer behind the core's scheduler seam.
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* seam exists so the CORE stays free of a global timer, not so each element
|
|
33
|
-
* invents its own.
|
|
26
|
+
* The browser's timer behind the core's scheduler seam. One shared instance rather than
|
|
27
|
+
* one per element: it holds no state, and the seam exists so the CORE stays free of a
|
|
28
|
+
* global timer, not so each element invents its own.
|
|
34
29
|
*/
|
|
35
30
|
export const domViewSwitcherScheduler: ViewSwitcherScheduler = {
|
|
36
31
|
schedule(callback: () => void, ms: number): ViewSwitcherTimerHandle {
|
|
@@ -62,19 +57,17 @@ export function applySwitcherIcon(icon: AdwIcon, iconName: string): void {
|
|
|
62
57
|
/**
|
|
63
58
|
* Read a declared page element into the core's page init.
|
|
64
59
|
*
|
|
65
|
-
* `getAttribute` returns `null` for an absent attribute, which is EXACTLY C's
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* no title" is no longer expressible.
|
|
60
|
+
* `getAttribute` returns `null` for an absent attribute, which is EXACTLY C's NULL, so
|
|
61
|
+
* values are passed through unchanged rather than defaulted to `''`. Do not add a
|
|
62
|
+
* `?? ''`: once an absent title has become the empty string, "the page has no title" is
|
|
63
|
+
* no longer expressible and the button-visibility rule cannot be implemented.
|
|
70
64
|
*/
|
|
71
65
|
export function readSwitcherPage(element: Element): AdwViewSwitcherPageInit {
|
|
72
66
|
const badge = Number.parseInt(element.getAttribute('badge-number') ?? '', 10);
|
|
73
67
|
return {
|
|
74
|
-
// A page with no `name` is the page named ''
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
// addressable by a name the author never wrote.
|
|
68
|
+
// A page with no `name` is the page named '', as in `<adw-view-stack>`: C stores
|
|
69
|
+
// the name verbatim, and an invented `page-<index>` would be addressable by a
|
|
70
|
+
// name the author never wrote.
|
|
78
71
|
name: element.getAttribute('name') ?? '',
|
|
79
72
|
title: element.getAttribute('title'),
|
|
80
73
|
iconName: element.getAttribute('icon-name'),
|
|
@@ -88,8 +81,8 @@ export function readSwitcherPage(element: Element): AdwViewSwitcherPageInit {
|
|
|
88
81
|
|
|
89
82
|
/**
|
|
90
83
|
* Paint `AdwIndicatorBin`'s badge/dot onto a span: the badge text when there is
|
|
91
|
-
* one, a bare dot when only `needs-attention` is set, nothing otherwise
|
|
92
|
-
*
|
|
84
|
+
* one, a bare dot when only `needs-attention` is set, nothing otherwise — C's
|
|
85
|
+
* `AdwIndicatorBin` plus the `.needs-attention` style class.
|
|
93
86
|
*/
|
|
94
87
|
export function applyIndicator(indicator: HTMLElement, badgeLabel: string, needsAttention: boolean): void {
|
|
95
88
|
indicator.textContent = badgeLabel;
|
|
@@ -100,7 +93,7 @@ export function applyIndicator(indicator: HTMLElement, badgeLabel: string, needs
|
|
|
100
93
|
/**
|
|
101
94
|
* Mirror the derived screen-reader description onto the element, REMOVING the
|
|
102
95
|
* attribute when there is none — `update_description_cb` resets the accessible
|
|
103
|
-
* property rather than setting it to `""
|
|
96
|
+
* property rather than setting it to `""`.
|
|
104
97
|
*/
|
|
105
98
|
export function applyDescription(element: HTMLElement, description: string): void {
|
|
106
99
|
if (description) element.setAttribute('aria-description', description);
|
package/src/entry-rows.spec.ts
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// driven by the SAME vectors the NativeScript renderer asserts against
|
|
3
3
|
// (`@gjsify/adwaita-core/conformance`).
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// compared this renderer to the C. This suite is that comparison — it drives the
|
|
10
|
-
// real elements through each scenario and reads back what a user would see.
|
|
5
|
+
// The vectors cover `update_empty`'s truth table, the apply button, the Enter key,
|
|
6
|
+
// max-length, and the caps-lock warning with its two suppression rules — all of which
|
|
7
|
+
// were missing from this renderer, not merely different. Each scenario drives the real
|
|
8
|
+
// elements and reads back what a user would see.
|
|
11
9
|
import { describe, expect, it } from '@gjsify/unit';
|
|
12
10
|
|
|
13
11
|
import {
|
|
@@ -141,9 +139,8 @@ export const AdwEntryRowsTest = async () => {
|
|
|
141
139
|
parts.row.maxLength = 0;
|
|
142
140
|
parts.row.text = '';
|
|
143
141
|
parts.row.maxLength = maxLength;
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
// is deliberately left unset.
|
|
142
|
+
// The `input` event path must clamp exactly like the property path, which
|
|
143
|
+
// is why `input.maxLength` (UTF-16 units) is deliberately left unset.
|
|
147
144
|
parts.input.value = text;
|
|
148
145
|
parts.input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
149
146
|
expect(parts.input.value).toBe(clamped);
|
|
@@ -166,8 +163,8 @@ export const AdwEntryRowsTest = async () => {
|
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
await it('activates the default BEFORE emitting entry-activated', () => {
|
|
169
|
-
//
|
|
170
|
-
//
|
|
166
|
+
// `gtk_widget_activate_default` runs before the `entry-activated` signal;
|
|
167
|
+
// implicit form submission is the web's spelling of that default activation.
|
|
171
168
|
const host = document.createElement('div');
|
|
172
169
|
document.body.appendChild(host);
|
|
173
170
|
host.innerHTML = '<form><adw-entry-row title="T" activates-default></adw-entry-row></form>';
|
|
@@ -210,9 +207,8 @@ export const AdwEntryRowsTest = async () => {
|
|
|
210
207
|
|
|
211
208
|
await describe('adw-entry-row change signals', async () => {
|
|
212
209
|
await it('emits both GtkEditable spellings on every buffer change', () => {
|
|
213
|
-
// libadwaita implements GtkEditable through a
|
|
214
|
-
//
|
|
215
|
-
// The two ports had each picked one and drifted apart.
|
|
210
|
+
// libadwaita implements GtkEditable through a DELEGATE, so an AdwEntryRow emits
|
|
211
|
+
// `changed` AND `notify::text` — a port must not pick just one.
|
|
216
212
|
const parts = mount('adw-entry-row', 'adw-entry-row');
|
|
217
213
|
const recorded = recordEvents(parts.row, ['changed', 'notify::text', 'notify::text-length']);
|
|
218
214
|
parts.row.text = 'Ada';
|
|
@@ -255,8 +251,8 @@ export const AdwEntryRowsTest = async () => {
|
|
|
255
251
|
|
|
256
252
|
await describe('adw-entry-row light-DOM children (GtkBuildable)', async () => {
|
|
257
253
|
await it('keeps author children instead of discarding them', () => {
|
|
258
|
-
// `replaceChildren(text, edit)`
|
|
259
|
-
//
|
|
254
|
+
// `replaceChildren(text, edit)` throws every authored child away silently,
|
|
255
|
+
// where `add_suffix` appends into a BOX.
|
|
260
256
|
const parts = mount('adw-entry-row', 'adw-entry-row', '<button id="go">Go</button>');
|
|
261
257
|
const go = parts.row.querySelector('#go') as HTMLElement;
|
|
262
258
|
expect(go).not.toBe(null);
|
|
@@ -281,9 +277,8 @@ export const AdwEntryRowsTest = async () => {
|
|
|
281
277
|
|
|
282
278
|
await describe('adw-entry-row click-to-focus (pressed_cb)', async () => {
|
|
283
279
|
await it('focuses the entry when the row body is clicked', () => {
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
// had this inverted: only the pencil focused, the body was inert.
|
|
280
|
+
// The click lands on the row, the header, the editable area, the indicator or
|
|
281
|
+
// an affordance box, and grabs focus — not only on the pencil.
|
|
287
282
|
const parts = mount('adw-entry-row', 'adw-entry-row');
|
|
288
283
|
parts.row.click();
|
|
289
284
|
expect(document.activeElement).toBe(parts.input);
|
|
@@ -365,20 +360,19 @@ export const AdwEntryRowsTest = async () => {
|
|
|
365
360
|
});
|
|
366
361
|
|
|
367
362
|
await it('keeps the peek toggle when a consumer adds a suffix', () => {
|
|
368
|
-
// add_suffix appends into a box
|
|
369
|
-
//
|
|
363
|
+
// `add_suffix` appends into a box and the toggle is installed through it, so
|
|
364
|
+
// both stay.
|
|
370
365
|
const parts = mount('adw-password-entry-row', 'adw-password-entry-row', '<button id="go">Go</button>');
|
|
371
366
|
const suffixes = parts.row.querySelector('.adw-password-entry-row-suffixes') as HTMLElement;
|
|
372
367
|
expect(suffixes.querySelector('.adw-password-entry-row-toggle')).not.toBe(null);
|
|
373
368
|
expect(suffixes.querySelector('#go')).not.toBe(null);
|
|
374
|
-
//
|
|
369
|
+
// The row's own toggle is the FIRST suffix.
|
|
375
370
|
expect(suffixes.children[0]?.classList.contains('adw-password-entry-row-toggle')).toBe(true);
|
|
376
371
|
parts.host.remove();
|
|
377
372
|
});
|
|
378
373
|
|
|
379
374
|
await it('inherits the entry row rather than copying it', () => {
|
|
380
|
-
// The
|
|
381
|
-
// copy-paste; the password row now IS an entry row.
|
|
375
|
+
// The password row IS an entry row, not a copy-paste of one.
|
|
382
376
|
const parts = mount('adw-password-entry-row', 'adw-password-entry-row');
|
|
383
377
|
parts.row.showApplyButton = true;
|
|
384
378
|
parts.input.focus();
|
package/src/index.ts
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
import '@gjsify/adwaita-fonts'; // Registers @font-face (fontsource pattern)
|
|
9
9
|
import { ADWAITA_WEB_CSS } from './styles.generated.js';
|
|
10
10
|
|
|
11
|
-
// Self-
|
|
12
|
-
// '@gjsify/adwaita-web'` enough to style the components under ANY bundler —
|
|
11
|
+
// Self-applied so `import '@gjsify/adwaita-web'` styles the components under ANY bundler:
|
|
13
12
|
// a separate `import '@gjsify/adwaita-web/style.css'` is a no-op under a gjsify
|
|
14
|
-
// `--app browser` build
|
|
15
|
-
// discards
|
|
13
|
+
// `--app browser` build, where css-as-string yields a string a side-effect import
|
|
14
|
+
// discards and the consumer ends up unstyled. Idempotent + browser-only.
|
|
16
15
|
if (typeof document !== 'undefined' && !document.getElementById('adwaita-web-style')) {
|
|
17
16
|
const style = document.createElement('style');
|
|
18
17
|
style.id = 'adwaita-web-style';
|
|
@@ -24,7 +23,6 @@ if (typeof document !== 'undefined' && !document.getElementById('adwaita-web-sty
|
|
|
24
23
|
// `AdwBreakpoint`, and the `breakpoint="…"` attribute wiring the split views use.
|
|
25
24
|
export { addBreakpoints, bindBreakpointSetter } from './breakpoints.js';
|
|
26
25
|
|
|
27
|
-
// Register custom elements (side-effect imports)
|
|
28
26
|
export { AdwAvatar } from './elements/adw-avatar.js';
|
|
29
27
|
export { AdwBanner } from './elements/adw-banner.js';
|
|
30
28
|
export { AdwCard } from './elements/adw-card.js';
|
|
@@ -43,23 +41,23 @@ export { AdwHeaderBar } from './elements/adw-header-bar.js';
|
|
|
43
41
|
export { AdwWindowTitle } from './elements/adw-window-title.js';
|
|
44
42
|
export { AdwButton } from './elements/adw-button.js';
|
|
45
43
|
export { AdwButtonContent } from './elements/adw-button-content.js';
|
|
46
|
-
// The ONE symbolic-icon node and the ONE toggle
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
44
|
+
// The ONE symbolic-icon node and the ONE toggle, exported before the widgets that build
|
|
45
|
+
// them so the barrel's definition order matches theirs. Each host ALSO imports them
|
|
46
|
+
// directly, which is what actually guarantees the tags are defined before a
|
|
47
|
+
// server-rendered host upgrades.
|
|
50
48
|
export { AdwIcon, createAdwIcon } from './elements/adw-icon.js';
|
|
51
49
|
export { AdwSwitch } from './elements/adw-switch.js';
|
|
52
50
|
// The two form-control primitives. ONE module, because upstream merges their
|
|
53
51
|
// stylesheet (`_checks.scss`; there is no `_radio.scss` in libadwaita) and
|
|
54
52
|
// everything but the corner radius, the glyph and the group is shared.
|
|
55
53
|
export { AdwCheckbox, AdwRadio } from './elements/adw-checks.js';
|
|
56
|
-
// The determinate progress indicator — <adw-spinner> covers only the
|
|
57
|
-
// indeterminate case.
|
|
54
|
+
// The determinate progress indicator — <adw-spinner> covers only the indeterminate case.
|
|
58
55
|
export { AdwProgressBar } from './elements/adw-progress-bar.js';
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
//
|
|
56
|
+
// A keyboard shortcut, drawn as keycaps. The accelerator GRAMMAR lives in
|
|
57
|
+
// @gjsify/adwaita-core; this element only builds the nodes.
|
|
58
|
+
export { AdwShortcutLabel } from './elements/adw-shortcut-label.js';
|
|
59
|
+
// The ONE popover surface, exported before its three hosts for the same reason as
|
|
60
|
+
// <adw-icon> above.
|
|
63
61
|
export { AdwPopover } from './elements/adw-popover.js';
|
|
64
62
|
export type { AdwPopoverAlign, AdwPopoverPosition, AdwPopoverRole } from './elements/adw-popover.js';
|
|
65
63
|
export { AdwSplitButton } from './elements/adw-split-button.js';
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
// vectors the NativeScript renderer and the headless core assert against
|
|
3
3
|
// (`@gjsify/adwaita-core/conformance`).
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// the
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// `popToTag()` stopped early at a `can-pop="false"` page and emitted N separate
|
|
11
|
-
// transitions instead of one, and a duplicate `tag` was accepted silently.
|
|
12
|
-
// Nothing failed, because nothing compared them. This suite is that comparison.
|
|
5
|
+
// Four rows of the shared table are the ones independent copies of the stack machine got
|
|
6
|
+
// wrong: a programmatic `pop()` IGNORES `can-pop` (which gates only the back button and
|
|
7
|
+
// the shortcut pops), `replace(['some-tag'])` resolves a tag belonging to a
|
|
8
|
+
// dynamically-pushed page, `popToTag()` pops in ONE atomic splice emitting one
|
|
9
|
+
// transition rather than N, and a duplicate `tag` is refused, not silently accepted.
|
|
13
10
|
import { describe, expect, it } from '@gjsify/unit';
|
|
14
11
|
|
|
15
12
|
import {
|
|
@@ -269,7 +266,7 @@ export const AdwNavigationViewTest = async () => {
|
|
|
269
266
|
expect(backButton(view)).toBe(null);
|
|
270
267
|
view.pushByTag('detail');
|
|
271
268
|
// The old element hardcoded "Back" here, where the C uses the title of
|
|
272
|
-
// the page the button reveals (adw-back-button.c query_tooltip
|
|
269
|
+
// the page the button reveals (adw-back-button.c query_tooltip).
|
|
273
270
|
expect(backButton(view)?.getAttribute('tooltip')).toBe('Home');
|
|
274
271
|
|
|
275
272
|
view.pop();
|
|
@@ -406,7 +403,7 @@ export const AdwNavigationViewTest = async () => {
|
|
|
406
403
|
|
|
407
404
|
await it('stops Alt+Left WITHOUT popping a can-pop="false" page', () => {
|
|
408
405
|
// GDK_EVENT_STOP so the key never reaches an enclosing navigation view
|
|
409
|
-
// (pop_shortcut_cb
|
|
406
|
+
// (pop_shortcut_cb).
|
|
410
407
|
const { adapter, view, host, page } = mountView();
|
|
411
408
|
adapter.add(page('root'));
|
|
412
409
|
adapter.add(page('detail'));
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// the core reasons over.
|
|
8
8
|
//
|
|
9
9
|
// Reference: refs/libadwaita/src/adw-preferences-dialog.c
|
|
10
|
-
// (adw_preferences_dialog_init's page/group/row model
|
|
10
|
+
// (adw_preferences_dialog_init's page/group/row model)
|
|
11
11
|
// Reference: refs/libadwaita/src/adw-action-row.c, adw-entry-row.c,
|
|
12
12
|
// adw-expander-row.c, adw-button-row.c (which rows ARE action rows)
|
|
13
13
|
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
@@ -22,16 +22,14 @@ import {
|
|
|
22
22
|
} from '@gjsify/adwaita-core';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* The rows that derive from `AdwActionRow` and therefore have their SUBTITLE
|
|
26
|
-
*
|
|
25
|
+
* The rows that derive from `AdwActionRow` and therefore have their SUBTITLE searched
|
|
26
|
+
* (`filter_search_results`).
|
|
27
27
|
*
|
|
28
|
-
* A tag-name set rather than an `instanceof` chain, because the browser
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* adw-expander-row.c:72, adw-button-row.c:74), so the text typed into an entry
|
|
34
|
-
* row is deliberately NOT searchable.
|
|
28
|
+
* A tag-name set rather than an `instanceof` chain, because the browser elements are all
|
|
29
|
+
* direct `HTMLElement` subclasses: the GObject hierarchy is not reproduced in the DOM, so
|
|
30
|
+
* the distinction has to be stated. The test is NOT "has a subtitle" —
|
|
31
|
+
* `adw-entry-row`, `adw-expander-row` and `adw-button-row` derive from
|
|
32
|
+
* `AdwPreferencesRow` in C, so text typed into an entry row is deliberately not searchable.
|
|
35
33
|
*/
|
|
36
34
|
const ACTION_ROW_TAGS: ReadonlySet<string> = new Set([
|
|
37
35
|
'adw-action-row',
|
|
@@ -42,11 +40,9 @@ const ACTION_ROW_TAGS: ReadonlySet<string> = new Set([
|
|
|
42
40
|
|
|
43
41
|
/**
|
|
44
42
|
* `ADW_IS_PREFERENCES_ROW` for the browser elements — the first clause of
|
|
45
|
-
* `row_has_title`
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* boxed list legitimately holds other things: a bare `<adw-button>` dropped in
|
|
49
|
-
* as a footer is not a preferences row and must not be searchable.
|
|
43
|
+
* `row_has_title`. Spelled out rather than inferred from the `adw-` prefix, because a
|
|
44
|
+
* group's boxed list legitimately holds other things: a bare `<adw-button>` dropped in as
|
|
45
|
+
* a footer is not a preferences row and must not be searchable.
|
|
50
46
|
*/
|
|
51
47
|
const PREFERENCES_ROW_TAGS: ReadonlySet<string> = new Set([
|
|
52
48
|
...ACTION_ROW_TAGS,
|
package/src/preferences.spec.ts
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
// <adw-preferences-dialog>, driven by the SAME vectors the NativeScript
|
|
3
3
|
// renderer asserts against (`@gjsify/adwaita-core/conformance`).
|
|
4
4
|
//
|
|
5
|
-
// Two things are
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// every page's children out of the page element and discarding the pages —
|
|
12
|
-
// leaving nothing to derive `General → Appearance` from.
|
|
5
|
+
// Two things are held here. The GROUP HEADER has five states, all five derived: an empty
|
|
6
|
+
// group must not paint a `.boxed-list` card (its `box-shadow` strokes a full-width
|
|
7
|
+
// hairline over nothing) and a one-line header carries the `single-line` class the
|
|
8
|
+
// stylesheet keys its metrics off. The SEARCH needs the page elements to survive — a
|
|
9
|
+
// dialog that hoists every page's children out and discards the pages leaves nothing to
|
|
10
|
+
// derive `General → Appearance` from.
|
|
13
11
|
import { describe, expect, it } from '@gjsify/unit';
|
|
14
12
|
|
|
15
13
|
import {
|
|
@@ -49,8 +47,8 @@ function mountGroup(options: {
|
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
host.appendChild(group);
|
|
52
|
-
// Set AFTER connect
|
|
53
|
-
//
|
|
50
|
+
// Set AFTER connect to exercise the attribute path, and via setAttribute so exact
|
|
51
|
+
// whitespace survives (` ` is a visible title).
|
|
54
52
|
if (options.title !== undefined && options.title !== null) group.setAttribute('title', options.title);
|
|
55
53
|
if (options.description !== undefined && options.description !== null) {
|
|
56
54
|
group.setAttribute('description', options.description);
|
|
@@ -97,8 +95,8 @@ function mountSearchDialog(pages: readonly PreferencesSearchPage[]): {
|
|
|
97
95
|
if (group.visible === false) groupEl.hidden = true;
|
|
98
96
|
|
|
99
97
|
for (const row of group.rows) {
|
|
100
|
-
// An action row has a searchable subtitle
|
|
101
|
-
//
|
|
98
|
+
// An action row has a searchable subtitle and an entry row does not — the
|
|
99
|
+
// point of the vector.
|
|
102
100
|
const rowEl = document.createElement(row.isActionRow ? 'adw-action-row' : 'adw-entry-row');
|
|
103
101
|
rowEl.setAttribute('title', row.title);
|
|
104
102
|
if (row.subtitle) rowEl.setAttribute('subtitle', row.subtitle);
|
|
@@ -107,8 +105,8 @@ function mountSearchDialog(pages: readonly PreferencesSearchPage[]): {
|
|
|
107
105
|
}
|
|
108
106
|
pageEl.appendChild(groupEl);
|
|
109
107
|
}
|
|
110
|
-
// Through the public add(), i.e. AFTER connect
|
|
111
|
-
//
|
|
108
|
+
// Through the public add(), i.e. AFTER connect: the path that can leave a page
|
|
109
|
+
// rendering outside the dialog card.
|
|
112
110
|
dialog.add(pageEl);
|
|
113
111
|
}
|
|
114
112
|
return { dialog, host };
|
|
@@ -170,7 +168,7 @@ export const AdwPreferencesTest = async () => {
|
|
|
170
168
|
const { group, host } = mountGroup({ title: 'Account', rowCount: 1 });
|
|
171
169
|
const foreign = document.createElement('adw-action-row');
|
|
172
170
|
document.body.appendChild(foreign);
|
|
173
|
-
// ADW_CRITICAL_CANNOT_REMOVE_CHILD
|
|
171
|
+
// ADW_CRITICAL_CANNOT_REMOVE_CHILD.
|
|
174
172
|
expect(group.removeRow(foreign)).toBe(false);
|
|
175
173
|
foreign.remove();
|
|
176
174
|
host.remove();
|