@swiftwc/ui 0.0.0-dev.66 → 0.0.0-dev.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/generated/components/h-stack.d.ts +4 -0
  2. package/generated/components/h-stack.js +4 -0
  3. package/generated/components/index.d.ts +1 -0
  4. package/generated/components/index.js +1 -0
  5. package/generated/components/label-view.d.ts +5 -0
  6. package/generated/components/label-view.js +5 -0
  7. package/generated/components/toggle-view.d.ts +28 -0
  8. package/generated/components/toggle-view.js +222 -0
  9. package/generated/components/v-stack.d.ts +4 -0
  10. package/generated/components/v-stack.js +4 -0
  11. package/generated/css/index.css +110 -31
  12. package/generated/events/index.d.ts +1 -0
  13. package/generated/events/index.js +1 -0
  14. package/generated/events/toggle-view.d.ts +9 -0
  15. package/generated/events/toggle-view.js +1 -0
  16. package/package.json +1 -1
  17. package/scss/_components.scss +2 -0
  18. package/scss/components/_date-picker.scss +15 -15
  19. package/scss/components/_h-stack.scss +17 -1
  20. package/scss/components/_index.scss +4 -0
  21. package/scss/components/_menu-view.scss +53 -49
  22. package/scss/components/_picker-view.scss +38 -39
  23. package/scss/components/_scroll-view-proxy.scss +4 -2
  24. package/scss/components/_section-view.scss +23 -22
  25. package/scss/components/_table-view.scss +6 -6
  26. package/scss/components/_text-field.scss +26 -26
  27. package/scss/components/_toggle-view.scss +79 -0
  28. package/scss/components/_tool-bar.scss +52 -52
  29. package/scss/mixins/_index.scss +9 -2
  30. package/scss/placeholders/_lists.scss +14 -12
  31. package/scss/transitions/_menu-view.scss +17 -15
  32. package/web-components.html-data/en.json +175 -0
@@ -2,6 +2,10 @@
2
2
  *
3
3
  * @attr {@spacingSet} spacing - The gap between the primary axis
4
4
  *
5
+ * @attr {@alignmentSet} alignment - The cross-axis alignment
6
+ * @attr {@distributionSet} distribution - The main-axis alignment
7
+ * @attr {@placementSet} placement - The main-axis alignment
8
+ *
5
9
  */
6
10
  export declare class HStack extends HTMLElement {
7
11
  constructor();
@@ -3,6 +3,10 @@ import { devFlags } from '../internal/utils';
3
3
  *
4
4
  * @attr {@spacingSet} spacing - The gap between the primary axis
5
5
  *
6
+ * @attr {@alignmentSet} alignment - The cross-axis alignment
7
+ * @attr {@distributionSet} distribution - The main-axis alignment
8
+ * @attr {@placementSet} placement - The main-axis alignment
9
+ *
6
10
  */
7
11
  export class HStack extends HTMLElement {
8
12
  constructor() {
@@ -39,6 +39,7 @@ export * from './tab-item';
39
39
  export * from './tab-view';
40
40
  export * from './table-view';
41
41
  export * from './text-field';
42
+ export * from './toggle-view';
42
43
  export * from './tool-bar-item-group';
43
44
  export * from './tool-bar-item';
44
45
  export * from './tool-bar';
@@ -39,6 +39,7 @@ export * from './tab-item';
39
39
  export * from './tab-view';
40
40
  export * from './table-view';
41
41
  export * from './text-field';
42
+ export * from './toggle-view';
42
43
  export * from './tool-bar-item-group';
43
44
  export * from './tool-bar-item';
44
45
  export * from './tool-bar';
@@ -1,3 +1,8 @@
1
+ /**
2
+ *
3
+ * @attr {@fontSet} font - Sets the default font for text in this view.
4
+ *
5
+ */
1
6
  export declare class LabelView extends HTMLElement {
2
7
  #private;
3
8
  static get observedAttributes(): string[];
@@ -1,4 +1,9 @@
1
1
  import { $, devFlags, renderLabelIcon, renderLabelTitle } from '../internal/utils';
2
+ /**
3
+ *
4
+ * @attr {@fontSet} font - Sets the default font for text in this view.
5
+ *
6
+ */
2
7
  export class LabelView extends HTMLElement {
3
8
  static get observedAttributes() {
4
9
  return ['system-image', 'title', 'line-limit', 'truncation-mode'];
@@ -0,0 +1,28 @@
1
+ import { FormAssociatedBase } from '../internal/class/form-associated-base';
2
+ declare const toggleStyles: readonly ["switch", "button"];
3
+ export type ToggleStyle = (typeof toggleStyles)[number];
4
+ /**
5
+ * @slot label
6
+ * @slot validity-options
7
+ */
8
+ export declare class ToggleView extends FormAssociatedBase {
9
+ #private;
10
+ static get observedAttributes(): string[];
11
+ static get template(): DocumentFragment;
12
+ constructor();
13
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
14
+ disconnectedCallback(): void;
15
+ connectedCallback(): void;
16
+ get toggleStyle(): ToggleStyle;
17
+ get isOn(): boolean;
18
+ set isOn(v: boolean);
19
+ get name(): string;
20
+ get value(): string | null;
21
+ set value(v: string | null);
22
+ setValidity: (flags?: ValidityStateFlags, message?: string, anchor?: HTMLElement) => void;
23
+ setCustomValidity: (message: string) => void;
24
+ formAssociatedCallback: (form: HTMLFormElement) => void;
25
+ formDisabledCallback: (disabled: boolean) => void;
26
+ formResetCallback: () => void;
27
+ }
28
+ export {};
@@ -0,0 +1,222 @@
1
+ var _a;
2
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
+ import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
4
+ import { MutationObserverSet } from '../internal/class/mutation-observer-set';
5
+ import { $, devFlags, kebabCase, onoff, renderLabel } from '../internal/utils';
6
+ const toggleStyles = ['switch', 'button'];
7
+ /**
8
+ * @slot label
9
+ * @slot validity-options
10
+ */
11
+ export class ToggleView extends FormAssociatedBase {
12
+ static get observedAttributes() {
13
+ return ['label', 'name', 'value', 'is-on', 'keyboard-type', 'required', 'disabled'];
14
+ }
15
+ static #template;
16
+ static get template() {
17
+ return (this.#template ??= $(String.raw `
18
+ <label part="root toggle-stack">
19
+ <div part="root toggle-label-stack">
20
+ <slot name="label"></slot>
21
+ </div>
22
+ <div part="root toggle-input-stack">
23
+ <!--<input type="checkbox" part="root input toggle-form-input">-->
24
+ <div part="root toggle-form-input" tabindex="0"></div>
25
+ </div>
26
+ <slot name="validity-options" hidden></slot>
27
+ </label>`));
28
+ }
29
+ #renderValidityMsgs = (entries) => {
30
+ if (devFlags.debug)
31
+ console.debug(`${_a.name} ⚡️ mutation`);
32
+ this.setValidity(this.validity, this.validationMessage);
33
+ };
34
+ #shadowRoot;
35
+ #customValidity = '';
36
+ #slots = new Map();
37
+ #validityObservers = new MutationObserverSet(this.#renderValidityMsgs);
38
+ #input;
39
+ #value = 'on';
40
+ #isOn = false;
41
+ #connected = false;
42
+ get #internals() {
43
+ return getInternals(this);
44
+ }
45
+ constructor() {
46
+ super();
47
+ this.#shadowRoot = this.attachShadow({ mode: 'closed' });
48
+ this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
49
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
50
+ this.#slots?.set(slot.name, slot);
51
+ CleanupRegistry.register(this, () => {
52
+ this.#slots = new Map();
53
+ });
54
+ CleanupRegistry.unregister(this, 'validities');
55
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleValiditiesSlotchange, this.#slots?.get('validity-options')).on(), 'validities');
56
+ this.#input = this.#shadowRoot.querySelector('[part*=toggle-form-input]') ?? undefined;
57
+ this.#input?.addEventListener('click', () => {
58
+ this.isOn = !this.isOn;
59
+ this.#sendValueToForm(this.#connected);
60
+ });
61
+ CleanupRegistry.register(this, onoff([{ types: 'focusin', listener: this.#handleFocusin }], this).on());
62
+ CleanupRegistry.register(this, onoff([{ types: 'keydown', listener: this.#handleInputKeydown }], this.#input).on());
63
+ // CleanupRegistry.register(this, onoff([{ types: 'input', listener: this.#handleInputInput }], this.#input).on())
64
+ }
65
+ attributeChangedCallback(name, oldValue, newValue) {
66
+ if (devFlags.debug)
67
+ console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
68
+ switch (name) {
69
+ case 'value':
70
+ this.value = String(newValue); // this.#input?.setAttribute('checked', newValue ?? '')
71
+ this.#sendValueToForm(this.#connected);
72
+ break;
73
+ case 'is-on':
74
+ this.isOn = newValue !== null; // this.#input?.setAttribute('checked', newValue ?? '')
75
+ this.#sendValueToForm(this.#connected);
76
+ break;
77
+ case 'required':
78
+ // this.#input?.setAttribute(name, newValue ?? '')
79
+ this.#sendValueToForm(this.#connected);
80
+ break;
81
+ case 'name':
82
+ this.#sendValueToForm(this.#connected);
83
+ break;
84
+ case 'label':
85
+ renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue);
86
+ break;
87
+ case 'disabled':
88
+ for (const el of this.#shadowRoot.querySelectorAll('input'))
89
+ el.toggleAttribute('disabled', !newValue);
90
+ break;
91
+ }
92
+ }
93
+ disconnectedCallback() {
94
+ super.disconnectedCallback();
95
+ this.#validityObservers.unobserveAll();
96
+ }
97
+ connectedCallback() {
98
+ super.connectedCallback();
99
+ // finally
100
+ // if (this.hasAttribute('value')) this.value = this.getAttribute('value') ?? ''
101
+ if (this.hasAttribute('is-on'))
102
+ this.isOn = this.hasAttribute('is-on');
103
+ this.#sendValueToForm(false);
104
+ this.#connected = true;
105
+ }
106
+ get toggleStyle() {
107
+ return toggleStyles.includes(this.getAttribute('toggle-style') ?? '') ? this.getAttribute('toggle-style') : 'switch';
108
+ }
109
+ get isOn() {
110
+ return this.#isOn;
111
+ }
112
+ set isOn(v) {
113
+ this.#isOn = Boolean(v);
114
+ this.#value = this.#isOn ? (this.getAttribute('value') ?? 'on') : null;
115
+ this.ariaChecked = `${this.#isOn}`;
116
+ }
117
+ #handleValiditiesSlotchange = ({ type, target: slot }) => {
118
+ if (devFlags.debug)
119
+ console.debug(`${_a.name} ⚡️ ${type}`);
120
+ if (!(slot instanceof HTMLSlotElement))
121
+ return;
122
+ const assigned = slot.assignedElements();
123
+ this.#validityObservers.syncObservations(assigned, ['value', 'label']);
124
+ this.#renderValidityMsgs([]);
125
+ };
126
+ #handleFocusin = ({ type, target }) => {
127
+ if (devFlags.debug)
128
+ console.debug(`${_a.name} ⚡️ ${type}`);
129
+ if (target === this)
130
+ this.#input?.focus();
131
+ };
132
+ #sendValueToForm = (dispatchEvent = true) => {
133
+ // input.value has already been updated/synced !!
134
+ if (this.matches(':disabled'))
135
+ return this.setValidity({});
136
+ if (this.hasAttribute('required') && !this.isOn) {
137
+ this.setValidity({ valueMissing: true });
138
+ }
139
+ else {
140
+ this.setValidity({});
141
+ }
142
+ const entries = new FormData();
143
+ if (this.value)
144
+ entries.append(this.name, this.value);
145
+ this.#internals.setFormValue(entries);
146
+ if (dispatchEvent)
147
+ this.dispatchEvent(new CustomEvent('commit', { detail: { value: this.value, isOn: this.isOn }, bubbles: true, composed: true }));
148
+ };
149
+ #handleInputKeydown = (evt) => {
150
+ if (devFlags.debug)
151
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
152
+ this.isOn = !this.isOn;
153
+ this.#sendValueToForm();
154
+ };
155
+ #handleInputInput = (evt) => {
156
+ if (devFlags.debug)
157
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
158
+ this.#sendValueToForm();
159
+ };
160
+ // Optional: form participation properties
161
+ get name() {
162
+ return this.getAttribute('name') ?? this.getAttribute('label') ?? this.querySelector(':scope>[slot=label]')?.textContent ?? '';
163
+ }
164
+ get value() {
165
+ return this.#value;
166
+ }
167
+ set value(v) {
168
+ this.#value = this.isOn ? String(v) : null;
169
+ }
170
+ setValidity = (flags, message, anchor) => {
171
+ // let msg
172
+ // if (message)
173
+ for (const k in flags) {
174
+ const key = k; // ✅ type-safe cast
175
+ if (true !== flags[key])
176
+ continue;
177
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
178
+ if (!el.matches('option'))
179
+ continue;
180
+ const { label, value } = el;
181
+ if (`${kebabCase(key)}` === value) {
182
+ message = label;
183
+ break;
184
+ }
185
+ else if (`${kebabCase(key)}:${message}` === value) {
186
+ message = label;
187
+ break;
188
+ }
189
+ }
190
+ }
191
+ if (!message)
192
+ for (const k in flags) {
193
+ const key = k; // ✅ type-safe cast
194
+ if (true !== flags[key])
195
+ continue;
196
+ message = kebabCase(key);
197
+ break;
198
+ }
199
+ if (devFlags.debug)
200
+ console.debug(`${_a.name} ⚡️ validity-change`);
201
+ return this.#internals.setValidity(flags, this.#customValidity || message, anchor ?? this.#input);
202
+ };
203
+ setCustomValidity = (message) => {
204
+ this.#customValidity = message;
205
+ if (this.#customValidity)
206
+ this.#internals.setValidity({ ...this.#internals.validity, customError: true }, message);
207
+ else
208
+ this.#sendValueToForm(false);
209
+ };
210
+ formAssociatedCallback = (form) => {
211
+ this.#sendValueToForm();
212
+ };
213
+ formDisabledCallback = (disabled) => {
214
+ for (const el of this.#shadowRoot.querySelectorAll('input'))
215
+ el.toggleAttribute('disabled', !disabled);
216
+ };
217
+ formResetCallback = () => {
218
+ this.value = '';
219
+ this.#sendValueToForm();
220
+ };
221
+ }
222
+ _a = ToggleView;
@@ -5,6 +5,10 @@
5
5
  *
6
6
  * @attr {@spacingSet} spacing - The gap between the primary axis
7
7
  *
8
+ * @attr {@alignmentSet} alignment - The cross-axis alignment
9
+ * @attr {@distributionSet} distribution - The main-axis alignment
10
+ * @attr {@placementSet} placement - The main-axis alignment
11
+ *
8
12
  */
9
13
  export declare class VStack extends HTMLElement {
10
14
  constructor();
@@ -6,6 +6,10 @@ import { devFlags } from '../internal/utils';
6
6
  *
7
7
  * @attr {@spacingSet} spacing - The gap between the primary axis
8
8
  *
9
+ * @attr {@alignmentSet} alignment - The cross-axis alignment
10
+ * @attr {@distributionSet} distribution - The main-axis alignment
11
+ * @attr {@placementSet} placement - The main-axis alignment
12
+ *
9
13
  */
10
14
  export class VStack extends HTMLElement {
11
15
  constructor() {
@@ -1134,6 +1134,10 @@
1134
1134
  :where(table-view)::part(table-footer-leading-stack),
1135
1135
  :where(table-view)::part(table-footer-principal-stack),
1136
1136
  :where(table-view)::part(table-footer-trailing-stack),
1137
+ :where(toggle-view)::part(toggle-stack),
1138
+ :where(toggle-view)::part(toggle-label-stack),
1139
+ :where(toggle-view)::part(toggle-input-stack),
1140
+ :where(toggle-view)::part(text-field-form-input),
1137
1141
  :where(text-field)::part(text-field-stack),
1138
1142
  :where(text-field)::part(text-field-label-stack),
1139
1143
  :where(text-field)::part(text-field-input-stack),
@@ -1421,8 +1425,8 @@
1421
1425
  :where(detail-placeholder > scroll-view) {
1422
1426
  overflow: clip auto;
1423
1427
  pointer-events: all;
1424
- overscroll-behavior: contain;
1425
1428
  -webkit-overflow-scrolling: touch;
1429
+ overscroll-behavior: contain;
1426
1430
  container: scroll-view/size;
1427
1431
  padding-block: var(--safe-area-inset-top) var(--safe-area-inset-bottom);
1428
1432
  padding-inline: var(--safe-area-inset-left) var(--safe-area-inset-right);
@@ -1911,8 +1915,8 @@
1911
1915
  }
1912
1916
  :where(navigation-stack > scroll-view, navigation-split-view > scroll-view, [is=sidebar-view] > scroll-view, body-view > scroll-view, [is=full-screen] > scroll-view, [is=sheet-view] > scroll-view) {
1913
1917
  overflow: clip auto;
1914
- overscroll-behavior: contain;
1915
1918
  -webkit-overflow-scrolling: touch;
1919
+ overscroll-behavior: contain;
1916
1920
  padding-block: var(--safe-area-inset-top) var(--safe-area-inset-bottom);
1917
1921
  padding-inline: var(--safe-area-inset-left) var(--safe-area-inset-right);
1918
1922
  container: scroll-view/size;
@@ -1993,8 +1997,6 @@
1993
1997
  :where(scroll-view-proxy:has(> v-stack, > h-stack) > v-stack,
1994
1998
  scroll-view-proxy:has(> v-stack, > h-stack) > h-stack) {
1995
1999
  position: relative;
1996
- overscroll-behavior: contain;
1997
- -webkit-overflow-scrolling: touch;
1998
2000
  scrollbar-width: thin;
1999
2001
  container: scroll-view-proxy/inline-size;
2000
2002
  }
@@ -2010,10 +2012,14 @@
2010
2012
  :where(scroll-view-proxy:has(> v-stack, > h-stack) > v-stack) {
2011
2013
  overflow: clip auto;
2012
2014
  scroll-snap-type: block mandatory;
2015
+ -webkit-overflow-scrolling: touch;
2016
+ overscroll-behavior-block: contain;
2013
2017
  }
2014
2018
  :where(scroll-view-proxy:has(> v-stack, > h-stack) > h-stack) {
2015
2019
  overflow: auto clip;
2016
2020
  scroll-snap-type: inline mandatory;
2021
+ -webkit-overflow-scrolling: touch;
2022
+ overscroll-behavior-inline: contain;
2017
2023
  }
2018
2024
  :where(scroll-view-proxy:has(> v-stack, > h-stack) > h-stack[padding]) {
2019
2025
  scroll-padding-inline: 1rem;
@@ -2039,9 +2045,36 @@
2039
2045
  :where(h-stack[template="auto spacer auto"]) {
2040
2046
  grid-template-columns: auto minmax(0, 1fr) auto;
2041
2047
  }
2048
+ :where(h-stack[template="repeat(1,spacer)"]) {
2049
+ grid-template-columns: repeat(1, minmax(0, 1fr));
2050
+ }
2051
+ :where(h-stack[template="repeat(2,spacer)"]) {
2052
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2053
+ }
2054
+ :where(h-stack[template="repeat(3,spacer)"]) {
2055
+ grid-template-columns: repeat(3, minmax(0, 1fr));
2056
+ }
2042
2057
  :where(h-stack[template="repeat(4,spacer)"]) {
2043
2058
  grid-template-columns: repeat(4, minmax(0, 1fr));
2044
2059
  }
2060
+ :where(h-stack[template="repeat(5,spacer)"]) {
2061
+ grid-template-columns: repeat(5, minmax(0, 1fr));
2062
+ }
2063
+ :where(h-stack[template="repeat(6,spacer)"]) {
2064
+ grid-template-columns: repeat(6, minmax(0, 1fr));
2065
+ }
2066
+ :where(h-stack[template="repeat(7,spacer)"]) {
2067
+ grid-template-columns: repeat(7, minmax(0, 1fr));
2068
+ }
2069
+ :where(h-stack[template="repeat(8,spacer)"]) {
2070
+ grid-template-columns: repeat(8, minmax(0, 1fr));
2071
+ }
2072
+ :where(h-stack[template="repeat(9,spacer)"]) {
2073
+ grid-template-columns: repeat(9, minmax(0, 1fr));
2074
+ }
2075
+ :where(h-stack[template="repeat(10,spacer)"]) {
2076
+ grid-template-columns: repeat(10, minmax(0, 1fr));
2077
+ }
2045
2078
  :where(h-stack[template="repeat(2,spacer) auto"]) {
2046
2079
  grid-template-columns: repeat(2, minmax(0, 1fr)) auto;
2047
2080
  }
@@ -2575,14 +2608,6 @@
2575
2608
  grid-template-rows: auto 1fr auto;
2576
2609
  grid-template-areas: "top-bar" "spacer" "bottom-bar";
2577
2610
  }
2578
- :where(tool-bar > *:not(sidebar-toggle), tool-bar > sidebar-toggle > tool-bar-item, tab-view > sidebar-toggle > tool-bar-item, navigation-split-view > sidebar-toggle > tool-bar-item) {
2579
- backdrop-filter: var(--liquid-glass-backdrop-filter);
2580
- box-shadow: var(--toolbar-cell-box-shadow);
2581
- min-inline-size: var(--toolbar-cell-min-size);
2582
- transform: var(--toolbar-cell-scale, );
2583
- filter: var(--toolbar-cell-filter, );
2584
- opacity: var(--toolbar-cell-opacity, );
2585
- }
2586
2611
  :where(tool-bar)::part(top-bar), :where(tool-bar)::part(bottom-bar) {
2587
2612
  position: relative;
2588
2613
  padding-inline: var(--safe-area-inset-left, 0px) var(--safe-area-inset-right, 0px);
@@ -2609,6 +2634,14 @@
2609
2634
  column-gap: var(--toolbar-col-gap);
2610
2635
  padding-inline: var(--toolbar-col-gap) var(--toolbar-col-gap);
2611
2636
  }
2637
+ :where(tool-bar > *:not(sidebar-toggle), tool-bar > sidebar-toggle > tool-bar-item, tab-view > sidebar-toggle > tool-bar-item, navigation-split-view > sidebar-toggle > tool-bar-item) {
2638
+ backdrop-filter: var(--liquid-glass-backdrop-filter);
2639
+ box-shadow: var(--toolbar-cell-box-shadow);
2640
+ min-inline-size: var(--toolbar-cell-min-size);
2641
+ transform: var(--toolbar-cell-scale, );
2642
+ filter: var(--toolbar-cell-filter, );
2643
+ opacity: var(--toolbar-cell-opacity, );
2644
+ }
2612
2645
  @media (min-width: 37rem) and (min-height: 27.75rem) {
2613
2646
  :where([is=sheet-view] tool-bar)::part(top-bar), :where([is=sheet-view] tool-bar)::part(bottom-bar) {
2614
2647
  --safe-area-inset-left: 0px;
@@ -3088,6 +3121,52 @@
3088
3121
  }
3089
3122
  }
3090
3123
  }
3124
+ @layer sw-components {
3125
+ :where(toggle-view) {
3126
+ grid-template-columns: minmax(0, 1fr);
3127
+ grid-template-rows: minmax(0, 1fr);
3128
+ --toggle--trigger-bg: lightgray;
3129
+ }
3130
+ :where(toggle-view)::part(toggle-stack) {
3131
+ grid-template-columns: auto minmax(0, 1fr);
3132
+ grid-template-rows: minmax(0, 1fr);
3133
+ column-gap: var(--labeled-content-column-gap);
3134
+ }
3135
+ :where(toggle-view)::part(toggle-label-stack) {
3136
+ color: var(--secondary);
3137
+ }
3138
+ :where(toggle-view)::part(toggle-input-stack) {
3139
+ place-items: stretch;
3140
+ place-content: stretch;
3141
+ }
3142
+ :where(toggle-view)::part(toggle-form-input):focus {
3143
+ outline: blue solid 5px;
3144
+ }
3145
+ :where(toggle-view)::part(toggle-form-input) {
3146
+ text-align: end;
3147
+ position: relative;
3148
+ display: grid;
3149
+ outline: red solid 3px;
3150
+ border-radius: 2rem;
3151
+ inline-size: 4rem;
3152
+ block-size: 1rem;
3153
+ background: var(--toggle--trigger-bg);
3154
+ }
3155
+ :where(toggle-view)::part(toggle-form-input)::before {
3156
+ content: "";
3157
+ display: grid;
3158
+ position: absolute;
3159
+ inset: 0 auto auto 0;
3160
+ inline-size: 1rem;
3161
+ block-size: 1rem;
3162
+ border-radius: 1rem;
3163
+ backdrop-filter: var(--liquid-glass-backdrop-filter);
3164
+ box-shadow: var(--liquid-glass-box-shadow);
3165
+ }
3166
+ toggle-view[aria-checked=true] {
3167
+ --toggle--trigger-bg: green;
3168
+ }
3169
+ }
3091
3170
  @layer sw-components {
3092
3171
  :where(labeled-content) {
3093
3172
  container: labeled-content/inline-size;
@@ -3250,8 +3329,8 @@
3250
3329
  pointer-events: none;
3251
3330
  }
3252
3331
  :where(menu-view)::part(menu-form) {
3253
- overscroll-behavior: contain;
3254
3332
  -webkit-overflow-scrolling: touch;
3333
+ overscroll-behavior: contain;
3255
3334
  --menu--dialog-max-inline-size: anchor-size();
3256
3335
  --menu--dialog-max-block-size: anchor-size();
3257
3336
  }
@@ -3302,7 +3381,7 @@
3302
3381
  --menu--dialog-max-inline-size: anchor-size();
3303
3382
  --menu--dialog-max-block-size: anchor-size();
3304
3383
  }
3305
- menu-view[open]:not(tool-bar-item > menu-view) {
3384
+ :where(menu-view[open]:not(tool-bar-item > menu-view)) {
3306
3385
  --menu--summary-scale: scale(0.01);
3307
3386
  --menu--summary-filter: blur(10px);
3308
3387
  }
@@ -4209,6 +4288,21 @@
4209
4288
  grid-template-areas: "header" "main" "footer";
4210
4289
  gap: 0.5rem;
4211
4290
  }
4291
+ :where(section-view)::part(section-header-stack), :where(section-view)::part(section-footer-stack) {
4292
+ pointer-events: none;
4293
+ }
4294
+ :where(section-view)::part(section-header-stack) {
4295
+ grid-area: header;
4296
+ }
4297
+ :where(section-view)::part(section-main-stack) {
4298
+ grid-area: main;
4299
+ }
4300
+ :where(section-view)::part(section-footer-stack) {
4301
+ grid-area: footer;
4302
+ }
4303
+ :where(section-view)::part(section-header-stack) {
4304
+ order: -1;
4305
+ }
4212
4306
  :where(section-view:has(> [slot=header]):not(:has(> [slot=footer]))) {
4213
4307
  grid-template-rows: auto minmax(max-content, 1fr);
4214
4308
  grid-template-areas: "header" "main";
@@ -4227,21 +4321,6 @@
4227
4321
  :where(section-view:not(:has(> [slot=footer])))::part(section-footer-stack) {
4228
4322
  display: none;
4229
4323
  }
4230
- :where(section-view)::part(section-header-stack), :where(section-view)::part(section-footer-stack) {
4231
- pointer-events: none;
4232
- }
4233
- :where(section-view)::part(section-header-stack) {
4234
- grid-area: header;
4235
- }
4236
- :where(section-view)::part(section-main-stack) {
4237
- grid-area: main;
4238
- }
4239
- :where(section-view)::part(section-footer-stack) {
4240
- grid-area: footer;
4241
- }
4242
- :where(section-view)::part(section-header-stack) {
4243
- order: -1;
4244
- }
4245
4324
  section-view {
4246
4325
  /* :where(&:not(& &))::part(section-footer-stack),
4247
4326
  :where(&:not(& &))::part(section-header-stack) {
@@ -4302,7 +4381,7 @@
4302
4381
  border-radius: 0 0 var(--insetlist-item-border-radius) var(--insetlist-item-border-radius);
4303
4382
  border-top: 1px solid var(--separator);
4304
4383
  }
4305
- :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-header-leading-stack), :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-header-principal-stack), :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-header-trailing-stack), :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-footer-leading-stack), :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-footer-principal-stack), :where(:where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view)))::part(table-footer-trailing-stack) {
4384
+ :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-header-leading-stack), :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-header-principal-stack), :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-header-trailing-stack), :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-footer-leading-stack), :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-footer-principal-stack), :where(table-view:not(table-view table-view, list-view table-view, [is=form-view] table-view))::part(table-footer-trailing-stack) {
4306
4385
  grid-auto-flow: column;
4307
4386
  grid-template-columns: minmax(0, 1fr);
4308
4387
  column-gap: var(--toolbar-col-gap);
@@ -5317,8 +5396,8 @@
5317
5396
  z-index: -1;
5318
5397
  }
5319
5398
  :where([is=tab-bar] > [is=form-view]) {
5320
- overscroll-behavior: contain;
5321
5399
  -webkit-overflow-scrolling: touch;
5400
+ overscroll-behavior: contain;
5322
5401
  pointer-events: all;
5323
5402
  touch-action: none;
5324
5403
  grid-auto-flow: column;
@@ -6,3 +6,4 @@ export * from './picker-view';
6
6
  export * from './scroll-view';
7
7
  export * from './tab-view';
8
8
  export * from './text-field';
9
+ export * from './toggle-view';
@@ -6,3 +6,4 @@ export * from './picker-view';
6
6
  export * from './scroll-view';
7
7
  export * from './tab-view';
8
8
  export * from './text-field';
9
+ export * from './toggle-view';
@@ -0,0 +1,9 @@
1
+ export type ToggleChangeDetail = {
2
+ isOn: boolean;
3
+ value: string | null;
4
+ };
5
+ declare global {
6
+ interface HTMLElementEventMap {
7
+ change: CustomEvent<ToggleChangeDetail>;
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftwc/ui",
3
- "version": "0.0.0-dev.66",
3
+ "version": "0.0.0-dev.67",
4
4
  "description": "Elegant SwiftUI-inspired web components for standalone web apps and web extensions.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -52,6 +52,8 @@
52
52
 
53
53
  @forward 'components/label-view';
54
54
 
55
+ @forward 'components/toggle-view';
56
+
55
57
  @forward 'components/labeled-content';
56
58
 
57
59
  // @forward 'components/button-view';
@@ -5,26 +5,26 @@
5
5
  :where(&) {
6
6
  grid-template-columns: minmax(0, 1fr);
7
7
  grid-template-rows: minmax(0, 1fr);
8
- }
9
8
 
10
- :where(&)::part(date-picker-stack) {
11
- grid-template-columns: auto minmax(0, 1fr);
12
- grid-template-rows: minmax(0, 1fr);
13
- }
9
+ &::part(date-picker-stack) {
10
+ grid-template-columns: auto minmax(0, 1fr);
11
+ grid-template-rows: minmax(0, 1fr);
12
+ }
14
13
 
15
- :where(&)::part(date-picker-label-stack) {
16
- // display: grid;
17
- }
14
+ &::part(date-picker-label-stack) {
15
+ // display: grid;
16
+ }
18
17
 
19
- :where(&)::part(date-picker-input-stack) {
20
- place-items: stretch;
21
- place-content: stretch;
18
+ &::part(date-picker-input-stack) {
19
+ place-items: stretch;
20
+ place-content: stretch;
22
21
 
23
- grid-auto-flow: column;
24
- }
22
+ grid-auto-flow: column;
23
+ }
25
24
 
26
- :where(&)::part(date-picker-form-input) {
27
- text-align: end;
25
+ &::part(date-picker-form-input) {
26
+ text-align: end;
27
+ }
28
28
  }
29
29
  }
30
30
  }