@timmo001/groundwork-ui 0.9.28 → 0.9.30
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/custom-elements.json +217 -12
- package/package.json +1 -1
- package/src/dismiss.ts +10 -1
- package/src/fields.ts +3 -0
- package/src/gw-alert.ts +1 -1
- package/src/gw-card.ts +45 -7
- package/src/gw-command-menu.ts +6 -0
- package/src/gw-dialog.ts +17 -0
- package/src/gw-input.ts +10 -0
- package/src/gw-notification.ts +6 -1
- package/src/gw-option-list.ts +3 -1
- package/src/gw-popover.ts +17 -0
- package/src/gw-select.ts +5 -0
- package/src/gw-theme-picker.ts +9 -0
- package/src/gw-toast.ts +1 -1
package/custom-elements.json
CHANGED
|
@@ -77,12 +77,43 @@
|
|
|
77
77
|
"privacy": "private",
|
|
78
78
|
"readonly": true
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
"kind": "field",
|
|
82
|
+
"name": "#question",
|
|
83
|
+
"privacy": "private",
|
|
84
|
+
"readonly": true
|
|
85
|
+
},
|
|
80
86
|
{
|
|
81
87
|
"kind": "field",
|
|
82
88
|
"name": "#view",
|
|
83
89
|
"privacy": "private",
|
|
84
90
|
"readonly": true
|
|
85
91
|
},
|
|
92
|
+
{
|
|
93
|
+
"kind": "method",
|
|
94
|
+
"name": "text",
|
|
95
|
+
"parameters": [
|
|
96
|
+
{
|
|
97
|
+
"name": "question",
|
|
98
|
+
"type": {
|
|
99
|
+
"text": "string"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "keep",
|
|
104
|
+
"type": {
|
|
105
|
+
"text": "string"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "discard",
|
|
110
|
+
"type": {
|
|
111
|
+
"text": "string"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"description": "Sets the question and its buttons' text, for an app in another language."
|
|
116
|
+
},
|
|
86
117
|
{
|
|
87
118
|
"kind": "field",
|
|
88
119
|
"name": "asking",
|
|
@@ -629,7 +660,7 @@
|
|
|
629
660
|
{
|
|
630
661
|
"kind": "variable",
|
|
631
662
|
"name": "fieldStyles",
|
|
632
|
-
"default": "css` :where(gw-input, gw-select, gw-switch, gw-checkbox) { display: flex; flex-direction: column; gap: var(--gw-space-2); font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } :where(gw-input, gw-select) .gw-field-heading { display: flex; gap: var(--gw-space-1); align-items: center; } :where(gw-input, gw-select) .gw-field-heading > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } /* The (i) button by the label that opens a field's longer help */ :where(gw-input, gw-select) .gw-info { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-pill); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } :where(gw-input, gw-select) .gw-info:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } :where(gw-input, gw-select) .gw-info:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) .gw-info[hidden] { display: none; } :where(gw-input, gw-select) .gw-info > .icon { width: 1rem; height: 1rem; fill: currentColor; } /* Sizes run xs to xl through --gw-field-scale, around 1 for medium, and the control's height follows the theme's density too */ :where(gw-input, gw-select)[size=\"xs\"] { --gw-field-scale: 0.6; } :where(gw-input, gw-select)[size=\"small\"] { --gw-field-scale: 0.8; } :where(gw-input, gw-select)[size=\"large\"] { --gw-field-scale: 1.2; } :where(gw-input, gw-select)[size=\"xl\"] { --gw-field-scale: 1.4; } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger) { --gw-field-size: var(--gw-field-scale, 1); --gw-icon-size: calc( 1.25rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); width: 100%; min-height: calc( 2.5rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); padding: 0 calc(var(--gw-space-3) * var(--gw-field-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-field-size)); color: var(--gw-color-text-strong); background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-control); transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } /* An icon inside the field, before the text, with the text moved clear of it */ gw-input .gw-input-control { position: relative; display: flex; align-items: center; } gw-input .gw-input-control > .icon { position: absolute; inset-inline-start: calc(var(--gw-space-3) * var(--gw-field-scale, 1)); width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); color: var(--gw-color-text-secondary); pointer-events: none; fill: currentColor; } gw-input .gw-input-control > .icon[hidden] { display: none; } gw-input .gw-input-control > .icon:not([hidden]) + input { padding-inline-start: calc( (var(--gw-space-3) * 2 + 1.125rem) * var(--gw-field-scale, 1) ); } /* A textarea keeps the field's padding on every side and grows by its corner, never sideways out of the layout */ gw-input textarea { display: block; padding-block: calc(var(--gw-space-2) * var(--gw-field-size)); line-height: 1.5; resize: vertical; } gw-input[monospace] :where(input, textarea) { font-family: var(--gw-font-mono); } gw-input .gw-optional { font-weight: var(--gw-font-weight-regular); color: var(--gw-color-text-secondary); } gw-input .gw-optional[hidden] { display: none; } /* The show and hide button sits inside the end of a password field, with the text kept clear of it */ gw-input .gw-reveal { position: absolute; inset-inline-end: calc(var(--gw-space-1) * var(--gw-field-scale, 1)); display: grid; place-items: center; width: calc(2rem * var(--gw-field-scale, 1)); height: calc(2rem * var(--gw-field-scale, 1)); padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-control); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-input .gw-reveal:hover:not(:disabled) { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-input .gw-reveal:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-input .gw-reveal:disabled { cursor: not-allowed; opacity: 0.5; } gw-input .gw-reveal[hidden] { display: none; } gw-input .gw-reveal > .icon { width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); fill: currentColor; } gw-input .gw-input-control:has(> .gw-reveal:not([hidden])) > input { padding-inline-end: calc( (var(--gw-space-1) + 2rem + var(--gw-space-1)) * var(--gw-field-scale, 1) ); } /* The trigger shows the chosen option, with its icon, and a chevron with room around it that turns over while the list is open */ gw-select .gw-select-trigger { display: flex; gap: calc(var(--gw-space-2) * var(--gw-field-size)); align-items: center; padding-inline-end: calc(var(--gw-space-3) * var(--gw-field-size)); text-align: start; cursor: pointer; } gw-select .gw-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* With an inline label the select sits among toolbar controls, so it's a pill that fits its content, like the toggles and buttons beside it */ gw-select[inline-label] { display: inline-flex; } gw-select[inline-label] .gw-select-trigger { width: auto; padding-inline: calc(var(--gw-space-4) * var(--gw-field-size)) calc(var(--gw-space-3) * var(--gw-field-size)); border-radius: var(--gw-radius-pill); } /* An inline label reads as a quiet prefix to the value */ gw-select .gw-select-inline-label { flex: none; color: var(--gw-color-text-secondary); } gw-select .gw-select-inline-label[hidden] { display: none; } gw-select .gw-select-value[data-placeholder] { color: var(--gw-color-text-secondary); } gw-select .gw-select-trigger > .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } gw-select .gw-select-trigger > .icon:last-child { color: var(--gw-color-text-secondary); transition: rotate var(--gw-motion-normal) var(--gw-motion-easing); } gw-select[open] .gw-select-trigger > .icon:last-child { rotate: 180deg; } gw-select .gw-select-trigger > .icon[hidden] { display: none; } /* The list opens under the trigger, growing from it, or as a bottom sheet sliding up on phones */ gw-select .gw-select-popup { position: fixed; inset: unset; box-sizing: border-box; max-width: calc(100vw - 12px); padding: 0; margin: 0; overflow: hidden; color: var(--gw-color-text-primary); background: var(--gw-color-surface-overlay); border: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-l); opacity: 0; scale: 1 0.96; transform-origin: top; transition: opacity var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing), display var(--gw-motion-normal) allow-discrete, overlay var(--gw-motion-normal) allow-discrete; } gw-select .gw-select-popup[data-placement=\"above\"] { transform-origin: bottom; } gw-select .gw-select-popup:popover-open { opacity: 1; scale: 1; } @starting-style { gw-select .gw-select-popup:popover-open { opacity: 0; scale: 1 0.96; } } gw-select .gw-select-popup[data-placement=\"sheet\"] { inset: auto 0 0; width: 100%; max-width: none; padding-block-end: env(safe-area-inset-bottom); border-end-start-radius: 0; border-end-end-radius: 0; scale: 1; translate: 0 100%; --gw-option-list-height: 60vh; } gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 0; } @starting-style { gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 100%; } } gw-select .gw-select-popup[data-placement=\"sheet\"]::backdrop { background: rgb(0 0 0 / 40%); } /* With multiple, a full-width Clear under the list empties the choice */ gw-select .gw-select-clear { display: block; width: 100%; min-height: 2.5rem; padding: 0 var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-block-start: var(--gw-border-width) solid var(--gw-color-border-quiet); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-select .gw-select-clear:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-select .gw-select-clear:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-select .gw-select-clear[hidden] { display: none; } :where(gw-input) .gw-input-control:focus-within > .icon { color: var(--gw-color-text-strong); } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger):hover { border-color: var(--gw-color-border-loud); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :where(input, textarea, .gw-select-trigger):focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) [aria-invalid=\"true\"] { border-color: var(--gw-color-border-danger); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-error { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-danger); } :where(gw-switch, gw-checkbox) > label { display: inline-flex; gap: var(--gw-space-3); align-items: center; font-size: var(--gw-font-size-s); cursor: pointer; } :where(gw-input, gw-switch, gw-checkbox, gw-select) .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } gw-checkbox input { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: var(--gw-color-fill-accent-resting); } gw-switch input { position: relative; flex: none; width: 2.5rem; height: 1.5rem; margin: 0; cursor: pointer; appearance: none; background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-loud); border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-normal) var(--gw-motion-easing), border-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input::after { position: absolute; inset-block-start: 0.1875rem; inset-inline-start: 0.1875rem; width: 1rem; height: 1rem; content: \"\"; background: var(--gw-color-text-secondary); border-radius: 50%; transition: translate var(--gw-motion-normal) var(--gw-motion-easing), background-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input:checked { background: var(--gw-color-fill-accent-resting); border-color: transparent; } gw-switch input:checked::after { translate: 1rem 0; background: var(--gw-color-on-accent); } gw-switch input:disabled { opacity: 0.5; } gw-range { display: flex; flex-direction: column; gap: var(--gw-space-2); min-width: 0; font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } gw-range > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } gw-range .gw-range-row { display: flex; gap: var(--gw-space-3); align-items: center; } gw-range .gw-range-control { position: relative; display: block; flex: 1; min-width: 0; } /* The value beside the track, with readout */ gw-range .gw-range-readout { min-width: 5ch; font-size: var(--gw-font-size-s); font-variant-numeric: tabular-nums; color: var(--gw-color-text-secondary); text-align: end; white-space: nowrap; } gw-range .gw-range-readout[hidden] { display: none; } gw-range input { display: block; width: 100%; margin: 0; accent-color: var(--gw-color-fill-accent-resting); cursor: pointer; } gw-range input:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } gw-range input:disabled { cursor: not-allowed; opacity: 0.5; } /* The value above the thumb while it's held */ gw-range .gw-range-bubble { position: absolute; bottom: calc(100% + var(--gw-space-1)); padding: var(--gw-space-1) var(--gw-space-2); font-size: var(--gw-font-size-xs); font-variant-numeric: tabular-nums; color: var(--gw-color-on-accent); white-space: nowrap; pointer-events: none; background: var(--gw-color-fill-accent-resting); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-s); translate: -50% 0; } gw-range .gw-range-bubble[hidden] { display: none; } gw-range .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } gw-range .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } `",
|
|
663
|
+
"default": "css` :where(gw-input, gw-select, gw-switch, gw-checkbox) { display: flex; flex-direction: column; gap: var(--gw-space-2); font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } :where(gw-input, gw-select) .gw-field-heading { display: flex; gap: var(--gw-space-1); align-items: center; } :where(gw-input, gw-select) .gw-field-heading > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } /* The (i) button by the label that opens a field's longer help */ :where(gw-input, gw-select) .gw-info { display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem; padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-pill); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } :where(gw-input, gw-select) .gw-info:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } :where(gw-input, gw-select) .gw-info:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) .gw-info[hidden] { display: none; } :where(gw-input, gw-select) .gw-info > .icon { width: 1rem; height: 1rem; fill: currentColor; } /* Sizes run xs to xl through --gw-field-scale, around 1 for medium, and the control's height follows the theme's density too */ :where(gw-input, gw-select)[size=\"xs\"] { --gw-field-scale: 0.6; } :where(gw-input, gw-select)[size=\"small\"] { --gw-field-scale: 0.8; } :where(gw-input, gw-select)[size=\"large\"] { --gw-field-scale: 1.2; } :where(gw-input, gw-select)[size=\"xl\"] { --gw-field-scale: 1.4; } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger) { --gw-field-size: var(--gw-field-scale, 1); --gw-icon-size: calc( 1.25rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); width: 100%; min-height: calc( 2.5rem * var(--gw-field-size) * var(--gw-control-scale, 1) ); padding: 0 calc(var(--gw-space-3) * var(--gw-field-size)); font: inherit; font-size: calc(var(--gw-font-size-s) * var(--gw-field-size)); color: var(--gw-color-text-strong); background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-control); transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } /* An icon inside the field, before the text, with the text moved clear of it */ gw-input .gw-input-control { position: relative; display: flex; align-items: center; } gw-input .gw-input-control > .icon { position: absolute; inset-inline-start: calc(var(--gw-space-3) * var(--gw-field-scale, 1)); width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); color: var(--gw-color-text-secondary); pointer-events: none; fill: currentColor; } gw-input .gw-input-control > .icon[hidden] { display: none; } gw-input .gw-input-control > .icon:not([hidden]) + input { padding-inline-start: calc( (var(--gw-space-3) * 2 + 1.125rem) * var(--gw-field-scale, 1) ); } /* A textarea keeps the field's padding on every side and grows by its corner, never sideways out of the layout */ gw-input textarea { display: block; /* Pill-shaped controls would make a tall box a stadium, so it rounds no more than a panel */ border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); padding-block: calc(var(--gw-space-2) * var(--gw-field-size)); line-height: 1.5; resize: vertical; } gw-input[monospace] :where(input, textarea) { font-family: var(--gw-font-mono); } gw-input .gw-optional { font-weight: var(--gw-font-weight-regular); color: var(--gw-color-text-secondary); } gw-input .gw-optional[hidden] { display: none; } /* The show and hide button sits inside the end of a password field, with the text kept clear of it */ gw-input .gw-reveal { position: absolute; inset-inline-end: calc(var(--gw-space-1) * var(--gw-field-scale, 1)); display: grid; place-items: center; width: calc(2rem * var(--gw-field-scale, 1)); height: calc(2rem * var(--gw-field-scale, 1)); padding: 0; color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-radius: var(--gw-radius-control); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-input .gw-reveal:hover:not(:disabled) { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-input .gw-reveal:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-input .gw-reveal:disabled { cursor: not-allowed; opacity: 0.5; } gw-input .gw-reveal[hidden] { display: none; } gw-input .gw-reveal > .icon { width: calc(1.125rem * var(--gw-field-scale, 1)); height: calc(1.125rem * var(--gw-field-scale, 1)); fill: currentColor; } gw-input .gw-input-control:has(> .gw-reveal:not([hidden])) > input { padding-inline-end: calc( (var(--gw-space-1) + 2rem + var(--gw-space-1)) * var(--gw-field-scale, 1) ); } /* The trigger shows the chosen option, with its icon, and a chevron with room around it that turns over while the list is open */ gw-select .gw-select-trigger { display: flex; gap: calc(var(--gw-space-2) * var(--gw-field-size)); align-items: center; padding-inline-end: calc(var(--gw-space-3) * var(--gw-field-size)); text-align: start; cursor: pointer; } gw-select .gw-select-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* With an inline label the select sits among toolbar controls, so it's a pill that fits its content, like the toggles and buttons beside it */ gw-select[inline-label] { display: inline-flex; } gw-select[inline-label] .gw-select-trigger { width: auto; padding-inline: calc(var(--gw-space-4) * var(--gw-field-size)) calc(var(--gw-space-3) * var(--gw-field-size)); border-radius: var(--gw-radius-pill); } /* An inline label reads as a quiet prefix to the value */ gw-select .gw-select-inline-label { flex: none; color: var(--gw-color-text-secondary); } gw-select .gw-select-inline-label[hidden] { display: none; } gw-select .gw-select-value[data-placeholder] { color: var(--gw-color-text-secondary); } gw-select .gw-select-trigger > .icon { flex: none; width: var(--gw-icon-size, 1.25rem); height: var(--gw-icon-size, 1.25rem); fill: currentColor; } gw-select .gw-select-trigger > .icon:last-child { color: var(--gw-color-text-secondary); transition: rotate var(--gw-motion-normal) var(--gw-motion-easing); } gw-select[open] .gw-select-trigger > .icon:last-child { rotate: 180deg; } gw-select .gw-select-trigger > .icon[hidden] { display: none; } /* The list opens under the trigger, growing from it, or as a bottom sheet sliding up on phones */ gw-select .gw-select-popup { position: fixed; inset: unset; box-sizing: border-box; max-width: calc(100vw - 12px); padding: 0; margin: 0; overflow: hidden; color: var(--gw-color-text-primary); background: var(--gw-color-surface-overlay); border: max(var(--gw-border-width), 1px) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-l); opacity: 0; scale: 1 0.96; transform-origin: top; transition: opacity var(--gw-motion-fast) var(--gw-motion-easing), scale var(--gw-motion-normal) var(--gw-motion-easing), translate var(--gw-motion-normal) var(--gw-motion-easing), display var(--gw-motion-normal) allow-discrete, overlay var(--gw-motion-normal) allow-discrete; } gw-select .gw-select-popup[data-placement=\"above\"] { transform-origin: bottom; } gw-select .gw-select-popup:popover-open { opacity: 1; scale: 1; } @starting-style { gw-select .gw-select-popup:popover-open { opacity: 0; scale: 1 0.96; } } gw-select .gw-select-popup[data-placement=\"sheet\"] { inset: auto 0 0; width: 100%; max-width: none; padding-block-end: env(safe-area-inset-bottom); border-end-start-radius: 0; border-end-end-radius: 0; scale: 1; translate: 0 100%; --gw-option-list-height: 60vh; } gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 0; } @starting-style { gw-select .gw-select-popup[data-placement=\"sheet\"]:popover-open { translate: 0 100%; } } gw-select .gw-select-popup[data-placement=\"sheet\"]::backdrop { background: rgb(0 0 0 / 40%); } /* With multiple, a full-width Clear under the list empties the choice */ gw-select .gw-select-clear { display: block; width: 100%; min-height: 2.5rem; padding: 0 var(--gw-space-3); font: inherit; font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-secondary); cursor: pointer; background: none; border: 0; border-block-start: var(--gw-border-width) solid var(--gw-color-border-quiet); transition: color var(--gw-motion-fast) var(--gw-motion-easing), background-color var(--gw-motion-fast) var(--gw-motion-easing); } gw-select .gw-select-clear:hover { color: var(--gw-color-text-strong); background: var(--gw-color-fill-neutral-hovered); } gw-select .gw-select-clear:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: calc(var(--gw-focus-width) * -1); } gw-select .gw-select-clear[hidden] { display: none; } :where(gw-input) .gw-input-control:focus-within > .icon { color: var(--gw-color-text-strong); } :where(gw-input, gw-select) :where(input, textarea, .gw-select-trigger):hover { border-color: var(--gw-color-border-loud); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :where(input, textarea, .gw-select-trigger):focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } :where(gw-input, gw-select) [aria-invalid=\"true\"] { border-color: var(--gw-color-border-danger); } :where(gw-input, gw-select, gw-switch, gw-checkbox) :disabled { color: var(--gw-color-text-disabled); cursor: not-allowed; } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } :where(gw-input, gw-select, gw-switch, gw-checkbox) .gw-error { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-danger); } :where(gw-switch, gw-checkbox) > label { display: inline-flex; gap: var(--gw-space-3); align-items: center; font-size: var(--gw-font-size-s); cursor: pointer; } :where(gw-input, gw-switch, gw-checkbox, gw-select) .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } gw-checkbox input { width: 1.125rem; height: 1.125rem; margin: 0; accent-color: var(--gw-color-fill-accent-resting); } gw-switch input { position: relative; flex: none; width: 2.5rem; height: 1.5rem; margin: 0; cursor: pointer; appearance: none; background: var(--gw-color-surface-lower); border: var(--gw-border-width) solid var(--gw-color-border-loud); border-radius: var(--gw-radius-pill); transition: background-color var(--gw-motion-normal) var(--gw-motion-easing), border-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input::after { position: absolute; inset-block-start: 0.1875rem; inset-inline-start: 0.1875rem; width: 1rem; height: 1rem; content: \"\"; background: var(--gw-color-text-secondary); border-radius: 50%; transition: translate var(--gw-motion-normal) var(--gw-motion-easing), background-color var(--gw-motion-normal) var(--gw-motion-easing); } gw-switch input:checked { background: var(--gw-color-fill-accent-resting); border-color: transparent; } gw-switch input:checked::after { translate: 1rem 0; background: var(--gw-color-on-accent); } gw-switch input:disabled { opacity: 0.5; } gw-range { display: flex; flex-direction: column; gap: var(--gw-space-2); min-width: 0; font-family: var(--gw-font-sans); color: var(--gw-color-text-primary); } gw-range > label { font-size: var(--gw-font-size-s); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } gw-range .gw-range-row { display: flex; gap: var(--gw-space-3); align-items: center; } gw-range .gw-range-control { position: relative; display: block; flex: 1; min-width: 0; } /* The value beside the track, with readout */ gw-range .gw-range-readout { min-width: 5ch; font-size: var(--gw-font-size-s); font-variant-numeric: tabular-nums; color: var(--gw-color-text-secondary); text-align: end; white-space: nowrap; } gw-range .gw-range-readout[hidden] { display: none; } gw-range input { display: block; width: 100%; margin: 0; accent-color: var(--gw-color-fill-accent-resting); cursor: pointer; } gw-range input:focus-visible { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } gw-range input:disabled { cursor: not-allowed; opacity: 0.5; } /* The value above the thumb while it's held */ gw-range .gw-range-bubble { position: absolute; bottom: calc(100% + var(--gw-space-1)); padding: var(--gw-space-1) var(--gw-space-2); font-size: var(--gw-font-size-xs); font-variant-numeric: tabular-nums; color: var(--gw-color-on-accent); white-space: nowrap; pointer-events: none; background: var(--gw-color-fill-accent-resting); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-s); translate: -50% 0; } gw-range .gw-range-bubble[hidden] { display: none; } gw-range .gw-hint { margin: 0; font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } gw-range .gw-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } `",
|
|
633
664
|
"description": "Field components render their native control in light DOM, never in a\nshadow root: password managers and `<label for>` can't reach across one,\nand a form only submits controls it can see. Their styles are adopted into\nwhichever document or shadow root they sit in."
|
|
634
665
|
},
|
|
635
666
|
{
|
|
@@ -1076,7 +1107,7 @@
|
|
|
1076
1107
|
"text": "readonly CSSStyleSheet[]"
|
|
1077
1108
|
},
|
|
1078
1109
|
"static": true,
|
|
1079
|
-
"default": "[ base, css` :host { display: block; } .alert { display: flex; gap: var(--gw-space-2); align-items: flex-start; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-tone-fill, var(--gw-color-fill-info-quiet)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-info)); border-inline-start-width: calc(var(--gw-border-width) * 4); border-radius: var(--gw-radius-control); } ::slotted(p) { margin: 0; } ::slotted([slot=\"actions\"]) { align-self: center; } ::slotted([slot=\"icon\"]), .icon { flex: none; color: var(--gw-tone, var(--gw-color-info)); } .body { flex: 1; min-width: 0; } strong { display: block; font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } `, ]",
|
|
1110
|
+
"default": "[ base, css` :host { display: block; } .alert { display: flex; gap: var(--gw-space-2); align-items: flex-start; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-tone-fill, var(--gw-color-fill-info-quiet)); border: var(--gw-border-width) solid var(--gw-tone-border, var(--gw-color-border-info)); border-inline-start-width: calc(var(--gw-border-width) * 4); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); } ::slotted(p) { margin: 0; } ::slotted([slot=\"actions\"]) { align-self: center; } ::slotted([slot=\"icon\"]), .icon { flex: none; color: var(--gw-tone, var(--gw-color-info)); } .body { flex: 1; min-width: 0; } strong { display: block; font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } `, ]",
|
|
1080
1111
|
"inheritedFrom": {
|
|
1081
1112
|
"name": "GwElement",
|
|
1082
1113
|
"module": "src/element.ts"
|
|
@@ -3805,7 +3836,7 @@
|
|
|
3805
3836
|
"text": "Properties"
|
|
3806
3837
|
},
|
|
3807
3838
|
"static": true,
|
|
3808
|
-
"default": "{ heading: {}, description: {}, icon: {}, level: { type: \"number\" }, href: {}, flush: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, lines: { type: \"number\" }, }",
|
|
3839
|
+
"default": "{ heading: {}, description: {}, icon: {}, level: { type: \"number\" }, href: {}, titleLink: { attribute: \"title-link\", type: \"boolean\", reflect: true }, flush: { type: \"boolean\", reflect: true }, loading: { type: \"boolean\", reflect: true }, lines: { type: \"number\" }, }",
|
|
3809
3840
|
"inheritedFrom": {
|
|
3810
3841
|
"name": "GwElement",
|
|
3811
3842
|
"module": "src/element.ts"
|
|
@@ -3818,7 +3849,7 @@
|
|
|
3818
3849
|
"text": "readonly CSSStyleSheet[]"
|
|
3819
3850
|
},
|
|
3820
3851
|
"static": true,
|
|
3821
|
-
"default": "[ base, css` :host { display: block; } .card { display: flex; flex-direction: column; gap: var(--gw-space-3); height: 100%; padding: var(--gw-space-4); color: inherit; text-decoration: none; background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-s); } :host([flush]) .card { padding: 0; overflow: hidden; } a.card { transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } a.card:hover, .card.linked:hover { border-color: var(--gw-color-border-accent); } /* A card following a link in its heading slot */ .card.linked { cursor: pointer; transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } .card.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } ::slotted([slot=\"heading\"]) { font: inherit; color: inherit; } ::slotted(a[slot=\"heading\"]) { text-decoration: none; outline: none; } header { display: flex; gap: var(--gw-space-2); align-items: center; } header > .icon { flex-shrink: 0; margin-inline-end: var(--gw-space-1); color: var(--gw-color-accent); } .titles { display: flex; flex: 1; flex-direction: column; gap: var(--gw-space-0-5); min-width: 0; } .title { margin: 0; font-size: var(--gw-font-size-m); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } /* The divider runs to the card's edges */ footer:not([hidden]) { display: flex; flex-direction: column; gap: inherit; margin-inline: calc(-1 * var(--gw-space-4)); padding: var(--gw-space-3) var(--gw-space-4) 0; border-top: var(--gw-border-width) solid var(--gw-color-border-normal); } :host([flush]) footer:not([hidden]) { margin-inline: 0; padding-bottom: var(--gw-space-3); } .body:not([hidden]) { display: flex; flex-direction: column; gap: inherit; } `, ]",
|
|
3852
|
+
"default": "[ base, css` :host { display: block; } .card { display: flex; flex-direction: column; gap: var(--gw-space-3); height: 100%; padding: var(--gw-space-4); color: inherit; text-decoration: none; background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-radius: var(--gw-radius-panel); box-shadow: var(--gw-shadow-s); } :host([flush]) .card { padding: 0; overflow: hidden; } a.card { transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } a.card:hover, .card.linked:hover { border-color: var(--gw-color-border-accent); } /* A card following a link in its heading slot */ .card.linked { cursor: pointer; transition: border-color var(--gw-motion-fast) var(--gw-motion-easing); } .card.focused { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } ::slotted([slot=\"heading\"]) { font: inherit; color: inherit; } ::slotted(a[slot=\"heading\"]) { text-decoration: none; outline: none; } /* With title-link, only the heading is the link */ .title a { color: inherit; text-decoration: none; border-radius: var(--gw-radius-chip); } .title a[href]:hover, :host([title-link]) ::slotted(a[slot=\"heading\"]:hover) { color: var(--gw-color-accent); text-decoration: underline; } .title a[href]:focus-visible, :host([title-link]) ::slotted(a[slot=\"heading\"]:focus-visible) { outline: var(--gw-focus-width) solid var(--gw-color-focus); outline-offset: var(--gw-focus-offset); } header { display: flex; gap: var(--gw-space-2); align-items: center; } header > .icon { flex-shrink: 0; margin-inline-end: var(--gw-space-1); color: var(--gw-color-accent); } .titles { display: flex; flex: 1; flex-direction: column; gap: var(--gw-space-0-5); min-width: 0; } .title { margin: 0; font-size: var(--gw-font-size-m); font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } .description { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } /* The divider runs to the card's edges */ footer:not([hidden]) { display: flex; flex-direction: column; gap: inherit; margin-inline: calc(-1 * var(--gw-space-4)); padding: var(--gw-space-3) var(--gw-space-4) 0; border-top: var(--gw-border-width) solid var(--gw-color-border-normal); } :host([flush]) footer:not([hidden]) { margin-inline: 0; padding-bottom: var(--gw-space-3); } .body:not([hidden]) { display: flex; flex-direction: column; gap: inherit; } `, ]",
|
|
3822
3853
|
"inheritedFrom": {
|
|
3823
3854
|
"name": "GwElement",
|
|
3824
3855
|
"module": "src/element.ts"
|
|
@@ -3866,6 +3897,15 @@
|
|
|
3866
3897
|
},
|
|
3867
3898
|
"default": "\"\""
|
|
3868
3899
|
},
|
|
3900
|
+
{
|
|
3901
|
+
"kind": "field",
|
|
3902
|
+
"name": "titleLink",
|
|
3903
|
+
"type": {
|
|
3904
|
+
"text": "boolean"
|
|
3905
|
+
},
|
|
3906
|
+
"description": "Makes only the heading the link, rather than the whole card.",
|
|
3907
|
+
"default": "false"
|
|
3908
|
+
},
|
|
3869
3909
|
{
|
|
3870
3910
|
"kind": "field",
|
|
3871
3911
|
"name": "flush",
|
|
@@ -3897,6 +3937,12 @@
|
|
|
3897
3937
|
"privacy": "private",
|
|
3898
3938
|
"readonly": true
|
|
3899
3939
|
},
|
|
3940
|
+
{
|
|
3941
|
+
"kind": "field",
|
|
3942
|
+
"name": "#titleAnchor",
|
|
3943
|
+
"privacy": "private",
|
|
3944
|
+
"readonly": true
|
|
3945
|
+
},
|
|
3900
3946
|
{
|
|
3901
3947
|
"kind": "field",
|
|
3902
3948
|
"name": "#titleSkeleton",
|
|
@@ -4366,6 +4412,13 @@
|
|
|
4366
4412
|
"description": "Makes the whole card a link to this address.",
|
|
4367
4413
|
"name": "href"
|
|
4368
4414
|
},
|
|
4415
|
+
{
|
|
4416
|
+
"type": {
|
|
4417
|
+
"text": "boolean"
|
|
4418
|
+
},
|
|
4419
|
+
"description": "Makes only the heading the link, from `href` or an `<a>` in the `heading` slot, so the rest of the card stays plain.",
|
|
4420
|
+
"name": "title-link"
|
|
4421
|
+
},
|
|
4369
4422
|
{
|
|
4370
4423
|
"type": {
|
|
4371
4424
|
"text": "boolean"
|
|
@@ -6037,7 +6090,7 @@
|
|
|
6037
6090
|
"text": "Properties"
|
|
6038
6091
|
},
|
|
6039
6092
|
"static": true,
|
|
6040
|
-
"default": "{ options: { type: \"json\" }, label: {}, placeholder: {}, shortcut: {}, open: { type: \"boolean\", reflect: true }, }",
|
|
6093
|
+
"default": "{ options: { type: \"json\" }, value: {}, label: {}, placeholder: {}, shortcut: {}, open: { type: \"boolean\", reflect: true }, }",
|
|
6041
6094
|
"inheritedFrom": {
|
|
6042
6095
|
"name": "GwElement",
|
|
6043
6096
|
"module": "src/element.ts"
|
|
@@ -6064,6 +6117,15 @@
|
|
|
6064
6117
|
},
|
|
6065
6118
|
"default": "[]"
|
|
6066
6119
|
},
|
|
6120
|
+
{
|
|
6121
|
+
"kind": "field",
|
|
6122
|
+
"name": "value",
|
|
6123
|
+
"type": {
|
|
6124
|
+
"text": "string"
|
|
6125
|
+
},
|
|
6126
|
+
"description": "The current command, marked and selected when the menu opens.",
|
|
6127
|
+
"default": "\"\""
|
|
6128
|
+
},
|
|
6067
6129
|
{
|
|
6068
6130
|
"kind": "field",
|
|
6069
6131
|
"name": "label",
|
|
@@ -6455,6 +6517,13 @@
|
|
|
6455
6517
|
"description": "The commands, as JSON.",
|
|
6456
6518
|
"name": "options"
|
|
6457
6519
|
},
|
|
6520
|
+
{
|
|
6521
|
+
"type": {
|
|
6522
|
+
"text": "string"
|
|
6523
|
+
},
|
|
6524
|
+
"description": "The current command, such as the page you're on. It's marked, and selected and scrolled into view each time the menu opens.",
|
|
6525
|
+
"name": "value"
|
|
6526
|
+
},
|
|
6458
6527
|
{
|
|
6459
6528
|
"type": {
|
|
6460
6529
|
"text": "string"
|
|
@@ -6552,7 +6621,7 @@
|
|
|
6552
6621
|
"text": "Properties"
|
|
6553
6622
|
},
|
|
6554
6623
|
"static": true,
|
|
6555
|
-
"default": "{ heading: {}, open: { type: \"boolean\", reflect: true }, closeLabel: { attribute: \"close-label\" }, }",
|
|
6624
|
+
"default": "{ heading: {}, open: { type: \"boolean\", reflect: true }, closeLabel: { attribute: \"close-label\" }, discardQuestion: { attribute: \"discard-question\" }, keepLabel: { attribute: \"keep-label\" }, discardLabel: { attribute: \"discard-label\" }, }",
|
|
6556
6625
|
"inheritedFrom": {
|
|
6557
6626
|
"name": "GwElement",
|
|
6558
6627
|
"module": "src/element.ts"
|
|
@@ -6596,6 +6665,30 @@
|
|
|
6596
6665
|
"description": "The close button's name, for an app in another language.",
|
|
6597
6666
|
"default": "\"Close\""
|
|
6598
6667
|
},
|
|
6668
|
+
{
|
|
6669
|
+
"kind": "field",
|
|
6670
|
+
"name": "discardQuestion",
|
|
6671
|
+
"type": {
|
|
6672
|
+
"text": "string"
|
|
6673
|
+
},
|
|
6674
|
+
"default": "\"Discard your changes?\""
|
|
6675
|
+
},
|
|
6676
|
+
{
|
|
6677
|
+
"kind": "field",
|
|
6678
|
+
"name": "keepLabel",
|
|
6679
|
+
"type": {
|
|
6680
|
+
"text": "string"
|
|
6681
|
+
},
|
|
6682
|
+
"default": "\"Keep editing\""
|
|
6683
|
+
},
|
|
6684
|
+
{
|
|
6685
|
+
"kind": "field",
|
|
6686
|
+
"name": "discardLabel",
|
|
6687
|
+
"type": {
|
|
6688
|
+
"text": "string"
|
|
6689
|
+
},
|
|
6690
|
+
"default": "\"Discard\""
|
|
6691
|
+
},
|
|
6599
6692
|
{
|
|
6600
6693
|
"kind": "field",
|
|
6601
6694
|
"name": "returnValue",
|
|
@@ -7021,6 +7114,27 @@
|
|
|
7021
7114
|
},
|
|
7022
7115
|
"description": "The close button's name, for an app in another language. Defaults to `Close`.",
|
|
7023
7116
|
"name": "close-label"
|
|
7117
|
+
},
|
|
7118
|
+
{
|
|
7119
|
+
"type": {
|
|
7120
|
+
"text": "string"
|
|
7121
|
+
},
|
|
7122
|
+
"description": "The question asked before closing with edits, for an app in another language. Defaults to `Discard your changes?`.",
|
|
7123
|
+
"name": "discard-question"
|
|
7124
|
+
},
|
|
7125
|
+
{
|
|
7126
|
+
"type": {
|
|
7127
|
+
"text": "string"
|
|
7128
|
+
},
|
|
7129
|
+
"description": "The button that goes back to editing. Defaults to `Keep editing`.",
|
|
7130
|
+
"name": "keep-label"
|
|
7131
|
+
},
|
|
7132
|
+
{
|
|
7133
|
+
"type": {
|
|
7134
|
+
"text": "string"
|
|
7135
|
+
},
|
|
7136
|
+
"description": "The button that throws the edits away. Defaults to `Discard`.",
|
|
7137
|
+
"name": "discard-label"
|
|
7024
7138
|
}
|
|
7025
7139
|
],
|
|
7026
7140
|
"superclass": {
|
|
@@ -9944,7 +10058,7 @@
|
|
|
9944
10058
|
"text": "Properties"
|
|
9945
10059
|
},
|
|
9946
10060
|
"static": true,
|
|
9947
|
-
"default": "{ label: {}, name: {}, type: {}, value: {}, placeholder: {}, autocomplete: {}, inputmode: {}, min: {}, max: {}, step: {}, hint: {}, info: {}, error: {}, required: { type: \"boolean\" }, optional: { type: \"boolean\" }, disabled: { type: \"boolean\" }, multiline: { type: \"boolean\", reflect: true }, rows: { type: \"number\" }, monospace: { type: \"boolean\", reflect: true }, reveal: { type: \"boolean\" }, size: { reflect: true }, icon: {}, labelHidden: { type: \"boolean\", attribute: \"label-hidden\", reflect: true }, }",
|
|
10061
|
+
"default": "{ label: {}, name: {}, type: {}, value: {}, placeholder: {}, autocomplete: {}, inputmode: {}, min: {}, max: {}, step: {}, maxlength: { type: \"number\" }, hint: {}, info: {}, error: {}, required: { type: \"boolean\" }, optional: { type: \"boolean\" }, disabled: { type: \"boolean\" }, multiline: { type: \"boolean\", reflect: true }, rows: { type: \"number\" }, monospace: { type: \"boolean\", reflect: true }, reveal: { type: \"boolean\" }, size: { reflect: true }, icon: {}, labelHidden: { type: \"boolean\", attribute: \"label-hidden\", reflect: true }, }",
|
|
9948
10062
|
"inheritedFrom": {
|
|
9949
10063
|
"name": "GwElement",
|
|
9950
10064
|
"module": "src/element.ts"
|
|
@@ -10034,6 +10148,15 @@
|
|
|
10034
10148
|
"description": "The step between values of a number, date or time field.",
|
|
10035
10149
|
"default": "\"\""
|
|
10036
10150
|
},
|
|
10151
|
+
{
|
|
10152
|
+
"kind": "field",
|
|
10153
|
+
"name": "maxlength",
|
|
10154
|
+
"type": {
|
|
10155
|
+
"text": "number"
|
|
10156
|
+
},
|
|
10157
|
+
"description": "The most characters it takes, or 0 for no limit.",
|
|
10158
|
+
"default": "0"
|
|
10159
|
+
},
|
|
10037
10160
|
{
|
|
10038
10161
|
"kind": "field",
|
|
10039
10162
|
"name": "hint",
|
|
@@ -10625,6 +10748,13 @@
|
|
|
10625
10748
|
"description": "The step between values of a `number`, date or time field, or `any`.",
|
|
10626
10749
|
"name": "step"
|
|
10627
10750
|
},
|
|
10751
|
+
{
|
|
10752
|
+
"type": {
|
|
10753
|
+
"text": "number"
|
|
10754
|
+
},
|
|
10755
|
+
"description": "The most characters it takes.",
|
|
10756
|
+
"name": "maxlength"
|
|
10757
|
+
},
|
|
10628
10758
|
{
|
|
10629
10759
|
"type": {
|
|
10630
10760
|
"text": "string"
|
|
@@ -12609,7 +12739,7 @@
|
|
|
12609
12739
|
"text": "Properties"
|
|
12610
12740
|
},
|
|
12611
12741
|
"static": true,
|
|
12612
|
-
"default": "{ heading: {}, icon: {}, tone: { reflect: true }, time: {}, unread: { type: \"boolean\", reflect: true }, }",
|
|
12742
|
+
"default": "{ heading: {}, icon: {}, tone: { reflect: true }, time: {}, unread: { type: \"boolean\", reflect: true }, dismissLabel: { attribute: \"dismiss-label\" }, }",
|
|
12613
12743
|
"inheritedFrom": {
|
|
12614
12744
|
"name": "GwElement",
|
|
12615
12745
|
"module": "src/element.ts"
|
|
@@ -12622,7 +12752,7 @@
|
|
|
12622
12752
|
"text": "readonly CSSStyleSheet[]"
|
|
12623
12753
|
},
|
|
12624
12754
|
"static": true,
|
|
12625
|
-
"default": "[ base, css` :host { display: block; } .card { display: grid; grid-template-columns: auto 1fr auto; gap: var(--gw-space-1) var(--gw-space-2); align-items: start; padding: var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-quiet); border-radius: var(--gw-radius-control); } /* An inset stripe, so unread and read cards line up */ :host([unread]) .card { box-shadow: inset calc(var(--gw-border-width) * 4) 0 0 var(--gw-tone, var(--gw-color-accent)); } :host([unread]:dir(rtl)) .card { box-shadow: inset calc(var(--gw-border-width) * -4) 0 0 var(--gw-tone, var(--gw-color-accent)); } .card > .icon { margin-block-start: 0.1em; color: var(--gw-tone, var(--gw-color-text-secondary)); } .card > .icon[hidden] { display: none; } .body { display: grid; gap: var(--gw-space-1); min-width: 0; } strong { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } time { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } time:empty { display: none; } ::slotted(p) { margin: 0; } .actions { display: flex; flex-wrap: wrap; gap: var(--gw-space-1); margin-block-start: var(--gw-space-1); } .close { margin: calc(var(--gw-space-1) * -1); } `, ]",
|
|
12755
|
+
"default": "[ base, css` :host { display: block; } .card { display: grid; grid-template-columns: auto 1fr auto; gap: var(--gw-space-1) var(--gw-space-2); align-items: start; padding: var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-primary); background: var(--gw-color-surface-raised); border: var(--gw-border-width) solid var(--gw-color-border-quiet); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); } /* An inset stripe, so unread and read cards line up */ :host([unread]) .card { box-shadow: inset calc(var(--gw-border-width) * 4) 0 0 var(--gw-tone, var(--gw-color-accent)); } :host([unread]:dir(rtl)) .card { box-shadow: inset calc(var(--gw-border-width) * -4) 0 0 var(--gw-tone, var(--gw-color-accent)); } .card > .icon { margin-block-start: 0.1em; color: var(--gw-tone, var(--gw-color-text-secondary)); } .card > .icon[hidden] { display: none; } .body { display: grid; gap: var(--gw-space-1); min-width: 0; } strong { font-weight: var(--gw-font-weight-strong); color: var(--gw-color-text-strong); } time { font-size: var(--gw-font-size-xs); color: var(--gw-color-text-secondary); } time:empty { display: none; } ::slotted(p) { margin: 0; } .actions { display: flex; flex-wrap: wrap; gap: var(--gw-space-1); margin-block-start: var(--gw-space-1); } .close { margin: calc(var(--gw-space-1) * -1); } `, ]",
|
|
12626
12756
|
"inheritedFrom": {
|
|
12627
12757
|
"name": "GwElement",
|
|
12628
12758
|
"module": "src/element.ts"
|
|
@@ -12668,6 +12798,14 @@
|
|
|
12668
12798
|
},
|
|
12669
12799
|
"default": "false"
|
|
12670
12800
|
},
|
|
12801
|
+
{
|
|
12802
|
+
"kind": "field",
|
|
12803
|
+
"name": "dismissLabel",
|
|
12804
|
+
"type": {
|
|
12805
|
+
"text": "string"
|
|
12806
|
+
},
|
|
12807
|
+
"default": "\"Dismiss\""
|
|
12808
|
+
},
|
|
12671
12809
|
{
|
|
12672
12810
|
"kind": "field",
|
|
12673
12811
|
"name": "#icon",
|
|
@@ -13053,6 +13191,13 @@
|
|
|
13053
13191
|
},
|
|
13054
13192
|
"description": "Marks it with a stripe until it's seen.",
|
|
13055
13193
|
"name": "unread"
|
|
13194
|
+
},
|
|
13195
|
+
{
|
|
13196
|
+
"type": {
|
|
13197
|
+
"text": "string"
|
|
13198
|
+
},
|
|
13199
|
+
"description": "The close button's name, for an app in another language. Defaults to `Dismiss`.",
|
|
13200
|
+
"name": "dismiss-label"
|
|
13056
13201
|
}
|
|
13057
13202
|
],
|
|
13058
13203
|
"superclass": {
|
|
@@ -14358,7 +14503,7 @@
|
|
|
14358
14503
|
"text": "Properties"
|
|
14359
14504
|
},
|
|
14360
14505
|
"static": true,
|
|
14361
|
-
"default": "{ heading: {}, confirm: { type: \"boolean\" }, closeLabel: { attribute: \"close-label\" }, }",
|
|
14506
|
+
"default": "{ heading: {}, confirm: { type: \"boolean\" }, closeLabel: { attribute: \"close-label\" }, discardQuestion: { attribute: \"discard-question\" }, keepLabel: { attribute: \"keep-label\" }, discardLabel: { attribute: \"discard-label\" }, }",
|
|
14362
14507
|
"inheritedFrom": {
|
|
14363
14508
|
"name": "GwElement",
|
|
14364
14509
|
"module": "src/element.ts"
|
|
@@ -14402,6 +14547,30 @@
|
|
|
14402
14547
|
"description": "The close button's name, for an app in another language.",
|
|
14403
14548
|
"default": "\"Close\""
|
|
14404
14549
|
},
|
|
14550
|
+
{
|
|
14551
|
+
"kind": "field",
|
|
14552
|
+
"name": "discardQuestion",
|
|
14553
|
+
"type": {
|
|
14554
|
+
"text": "string"
|
|
14555
|
+
},
|
|
14556
|
+
"default": "\"Discard your changes?\""
|
|
14557
|
+
},
|
|
14558
|
+
{
|
|
14559
|
+
"kind": "field",
|
|
14560
|
+
"name": "keepLabel",
|
|
14561
|
+
"type": {
|
|
14562
|
+
"text": "string"
|
|
14563
|
+
},
|
|
14564
|
+
"default": "\"Keep editing\""
|
|
14565
|
+
},
|
|
14566
|
+
{
|
|
14567
|
+
"kind": "field",
|
|
14568
|
+
"name": "discardLabel",
|
|
14569
|
+
"type": {
|
|
14570
|
+
"text": "string"
|
|
14571
|
+
},
|
|
14572
|
+
"default": "\"Discard\""
|
|
14573
|
+
},
|
|
14405
14574
|
{
|
|
14406
14575
|
"kind": "field",
|
|
14407
14576
|
"name": "returnValue",
|
|
@@ -14859,6 +15028,27 @@
|
|
|
14859
15028
|
},
|
|
14860
15029
|
"description": "The close button's name, for an app in another language. Defaults to `Close`.",
|
|
14861
15030
|
"name": "close-label"
|
|
15031
|
+
},
|
|
15032
|
+
{
|
|
15033
|
+
"type": {
|
|
15034
|
+
"text": "string"
|
|
15035
|
+
},
|
|
15036
|
+
"description": "The question asked before closing with edits, for an app in another language. Defaults to `Discard your changes?`.",
|
|
15037
|
+
"name": "discard-question"
|
|
15038
|
+
},
|
|
15039
|
+
{
|
|
15040
|
+
"type": {
|
|
15041
|
+
"text": "string"
|
|
15042
|
+
},
|
|
15043
|
+
"description": "The button that goes back to editing. Defaults to `Keep editing`.",
|
|
15044
|
+
"name": "keep-label"
|
|
15045
|
+
},
|
|
15046
|
+
{
|
|
15047
|
+
"type": {
|
|
15048
|
+
"text": "string"
|
|
15049
|
+
},
|
|
15050
|
+
"description": "The button that throws the edits away. Defaults to `Discard`.",
|
|
15051
|
+
"name": "discard-label"
|
|
14862
15052
|
}
|
|
14863
15053
|
],
|
|
14864
15054
|
"superclass": {
|
|
@@ -16473,7 +16663,7 @@
|
|
|
16473
16663
|
"text": "Properties"
|
|
16474
16664
|
},
|
|
16475
16665
|
"static": true,
|
|
16476
|
-
"default": "{ label: {}, name: {}, value: {}, multiple: { type: \"boolean\", reflect: true }, values: { type: \"json\" }, hint: {}, info: {}, placeholder: {}, search: {}, disabled: { type: \"boolean\" }, open: { type: \"boolean\", reflect: true }, options: { type: \"json\" }, labelHidden: { type: \"boolean\", attribute: \"label-hidden\" }, inlineLabel: { type: \"boolean\", attribute: \"inline-label\", reflect: true }, size: { reflect: true }, }",
|
|
16666
|
+
"default": "{ label: {}, name: {}, value: {}, multiple: { type: \"boolean\", reflect: true }, values: { type: \"json\" }, hint: {}, info: {}, placeholder: {}, search: {}, disabled: { type: \"boolean\" }, open: { type: \"boolean\", reflect: true }, options: { type: \"json\" }, labelHidden: { type: \"boolean\", attribute: \"label-hidden\" }, inlineLabel: { type: \"boolean\", attribute: \"inline-label\", reflect: true }, size: { reflect: true }, clearLabel: { attribute: \"clear-label\" }, }",
|
|
16477
16667
|
"inheritedFrom": {
|
|
16478
16668
|
"name": "GwElement",
|
|
16479
16669
|
"module": "src/element.ts"
|
|
@@ -16601,6 +16791,14 @@
|
|
|
16601
16791
|
},
|
|
16602
16792
|
"default": "\"medium\""
|
|
16603
16793
|
},
|
|
16794
|
+
{
|
|
16795
|
+
"kind": "field",
|
|
16796
|
+
"name": "clearLabel",
|
|
16797
|
+
"type": {
|
|
16798
|
+
"text": "string"
|
|
16799
|
+
},
|
|
16800
|
+
"default": "\"Clear\""
|
|
16801
|
+
},
|
|
16604
16802
|
{
|
|
16605
16803
|
"kind": "field",
|
|
16606
16804
|
"name": "#id",
|
|
@@ -17170,6 +17368,13 @@
|
|
|
17170
17368
|
},
|
|
17171
17369
|
"description": "The field's size, 40px tall at medium. Defaults to `medium`.",
|
|
17172
17370
|
"name": "size"
|
|
17371
|
+
},
|
|
17372
|
+
{
|
|
17373
|
+
"type": {
|
|
17374
|
+
"text": "string"
|
|
17375
|
+
},
|
|
17376
|
+
"description": "The button that clears a multiple choice, for an app in another language. Defaults to `Clear`.",
|
|
17377
|
+
"name": "clear-label"
|
|
17173
17378
|
}
|
|
17174
17379
|
],
|
|
17175
17380
|
"superclass": {
|
|
@@ -21462,7 +21667,7 @@
|
|
|
21462
21667
|
"text": "readonly CSSStyleSheet[]"
|
|
21463
21668
|
},
|
|
21464
21669
|
"static": true,
|
|
21465
|
-
"default": "[ base, css` :host { position: fixed; inset: auto var(--gw-space-4) var(--gw-space-4) auto; width: min(22rem, calc(100vw - 2 * var(--gw-space-4))); padding: 0; margin: 0; overflow: visible; color: inherit; pointer-events: none; user-select: none; background: none; border: 0; } :host(:dir(rtl)) { inset: auto auto var(--gw-space-4) var(--gw-space-4); } :host(:not(:popover-open)) { display: none; } .list { display: flex; flex-direction: column; gap: var(--gw-space-1); align-items: flex-end; } .toast { max-width: 100%; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-strong); background: var(--gw-color-surface-overlay); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-inline-start: calc(var(--gw-border-width) * 4) solid var(--gw-toast-tone); border-radius: var(--gw-radius-control); box-shadow: var(--gw-shadow-m); } `, ]",
|
|
21670
|
+
"default": "[ base, css` :host { position: fixed; inset: auto var(--gw-space-4) var(--gw-space-4) auto; width: min(22rem, calc(100vw - 2 * var(--gw-space-4))); padding: 0; margin: 0; overflow: visible; color: inherit; pointer-events: none; user-select: none; background: none; border: 0; } :host(:dir(rtl)) { inset: auto auto var(--gw-space-4) var(--gw-space-4); } :host(:not(:popover-open)) { display: none; } .list { display: flex; flex-direction: column; gap: var(--gw-space-1); align-items: flex-end; } .toast { max-width: 100%; padding: var(--gw-space-2) var(--gw-space-3); font-size: var(--gw-font-size-s); color: var(--gw-color-text-strong); background: var(--gw-color-surface-overlay); border: var(--gw-border-width) solid var(--gw-color-border-normal); border-inline-start: calc(var(--gw-border-width) * 4) solid var(--gw-toast-tone); border-radius: min(var(--gw-radius-control), var(--gw-radius-panel)); box-shadow: var(--gw-shadow-m); } `, ]",
|
|
21466
21671
|
"inheritedFrom": {
|
|
21467
21672
|
"name": "GwElement",
|
|
21468
21673
|
"module": "src/element.ts"
|
package/package.json
CHANGED
package/src/dismiss.ts
CHANGED
|
@@ -74,10 +74,12 @@ export class Dismissal {
|
|
|
74
74
|
"Discard",
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
+
readonly #question = h("p", {}, "Discard your changes?");
|
|
78
|
+
|
|
77
79
|
readonly #view = h(
|
|
78
80
|
"div",
|
|
79
81
|
{ class: "discard", role: "alert" },
|
|
80
|
-
|
|
82
|
+
this.#question,
|
|
81
83
|
h("footer", {}, this.#keep, this.#discard),
|
|
82
84
|
);
|
|
83
85
|
|
|
@@ -107,6 +109,13 @@ export class Dismissal {
|
|
|
107
109
|
});
|
|
108
110
|
}
|
|
109
111
|
|
|
112
|
+
/** Sets the question and its buttons' text, for an app in another language. */
|
|
113
|
+
text(question: string, keep: string, discard: string) {
|
|
114
|
+
this.#question.textContent = question;
|
|
115
|
+
this.#keep.textContent = keep;
|
|
116
|
+
this.#discard.textContent = discard;
|
|
117
|
+
}
|
|
118
|
+
|
|
110
119
|
/** Whether it's showing the question rather than the content. */
|
|
111
120
|
get asking() {
|
|
112
121
|
return this.#surface.dataset.view === "discard";
|
package/src/fields.ts
CHANGED
|
@@ -140,6 +140,9 @@ export const fieldStyles = css`
|
|
|
140
140
|
corner, never sideways out of the layout */
|
|
141
141
|
gw-input textarea {
|
|
142
142
|
display: block;
|
|
143
|
+
/* Pill-shaped controls would make a tall box a stadium, so it rounds no
|
|
144
|
+
more than a panel */
|
|
145
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
143
146
|
padding-block: calc(var(--gw-space-2) * var(--gw-field-size));
|
|
144
147
|
line-height: 1.5;
|
|
145
148
|
resize: vertical;
|
package/src/gw-alert.ts
CHANGED
|
@@ -70,7 +70,7 @@ export class GwAlert extends GwElement {
|
|
|
70
70
|
border: var(--gw-border-width) solid
|
|
71
71
|
var(--gw-tone-border, var(--gw-color-border-info));
|
|
72
72
|
border-inline-start-width: calc(var(--gw-border-width) * 4);
|
|
73
|
-
border-radius: var(--gw-radius-control);
|
|
73
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
::slotted(p) {
|
package/src/gw-card.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { base, createIcon, setIconPath } from "./styles.js";
|
|
|
29
29
|
* @attr {string} icon - SVG path data for an icon before the heading, such as on a card that links to a section.
|
|
30
30
|
* @attr {number} level - The heading's level for assistive tech, 2 by default. Use 3 for a card under a section heading.
|
|
31
31
|
* @attr {string} href - Makes the whole card a link to this address.
|
|
32
|
+
* @attr {boolean} title-link - Makes only the heading the link, from `href` or an `<a>` in the `heading` slot, so the rest of the card stays plain.
|
|
32
33
|
* @attr {boolean} flush - Drops the padding, for content that runs to the edges.
|
|
33
34
|
* @attr {boolean} loading - Shows skeleton lines for the content and any unknown heading.
|
|
34
35
|
* @attr {number} lines - How many skeleton lines while loading. Defaults to 3.
|
|
@@ -52,6 +53,7 @@ export class GwCard extends GwElement {
|
|
|
52
53
|
icon: {},
|
|
53
54
|
level: { type: "number" },
|
|
54
55
|
href: {},
|
|
56
|
+
titleLink: { attribute: "title-link", type: "boolean", reflect: true },
|
|
55
57
|
flush: { type: "boolean", reflect: true },
|
|
56
58
|
loading: { type: "boolean", reflect: true },
|
|
57
59
|
lines: { type: "number" },
|
|
@@ -113,6 +115,25 @@ export class GwCard extends GwElement {
|
|
|
113
115
|
outline: none;
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
/* With title-link, only the heading is the link */
|
|
119
|
+
.title a {
|
|
120
|
+
color: inherit;
|
|
121
|
+
text-decoration: none;
|
|
122
|
+
border-radius: var(--gw-radius-chip);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.title a[href]:hover,
|
|
126
|
+
:host([title-link]) ::slotted(a[slot="heading"]:hover) {
|
|
127
|
+
color: var(--gw-color-accent);
|
|
128
|
+
text-decoration: underline;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.title a[href]:focus-visible,
|
|
132
|
+
:host([title-link]) ::slotted(a[slot="heading"]:focus-visible) {
|
|
133
|
+
outline: var(--gw-focus-width) solid var(--gw-color-focus);
|
|
134
|
+
outline-offset: var(--gw-focus-offset);
|
|
135
|
+
}
|
|
136
|
+
|
|
116
137
|
header {
|
|
117
138
|
display: flex;
|
|
118
139
|
gap: var(--gw-space-2);
|
|
@@ -175,6 +196,8 @@ export class GwCard extends GwElement {
|
|
|
175
196
|
/** The heading's level for assistive tech. */
|
|
176
197
|
declare level: number;
|
|
177
198
|
declare href: string;
|
|
199
|
+
/** Makes only the heading the link, rather than the whole card. */
|
|
200
|
+
declare titleLink: boolean;
|
|
178
201
|
declare flush: boolean;
|
|
179
202
|
declare loading: boolean;
|
|
180
203
|
/** How many lines of skeleton stand in for the content while loading. */
|
|
@@ -182,6 +205,9 @@ export class GwCard extends GwElement {
|
|
|
182
205
|
|
|
183
206
|
readonly #title = h("span");
|
|
184
207
|
|
|
208
|
+
// A link only with title-link and href; without an href it's plain text
|
|
209
|
+
readonly #titleAnchor = h("a", {}, this.#title);
|
|
210
|
+
|
|
185
211
|
readonly #titleSkeleton = h("gw-skeleton-text");
|
|
186
212
|
|
|
187
213
|
readonly #headingSlot = h("slot", { name: "heading" });
|
|
@@ -189,7 +215,7 @@ export class GwCard extends GwElement {
|
|
|
189
215
|
readonly #heading = h(
|
|
190
216
|
"div",
|
|
191
217
|
{ class: "title", part: "heading", role: "heading", "aria-level": "2" },
|
|
192
|
-
this.#
|
|
218
|
+
this.#titleAnchor,
|
|
193
219
|
this.#headingSlot,
|
|
194
220
|
this.#titleSkeleton,
|
|
195
221
|
);
|
|
@@ -242,6 +268,7 @@ export class GwCard extends GwElement {
|
|
|
242
268
|
this.icon = "";
|
|
243
269
|
this.level = 2;
|
|
244
270
|
this.href = "";
|
|
271
|
+
this.titleLink = false;
|
|
245
272
|
this.flush = false;
|
|
246
273
|
this.loading = false;
|
|
247
274
|
this.lines = 3;
|
|
@@ -251,7 +278,7 @@ export class GwCard extends GwElement {
|
|
|
251
278
|
this.addEventListener("click", (event) => {
|
|
252
279
|
const link = this.#link();
|
|
253
280
|
|
|
254
|
-
if (link === null || this.loading) return;
|
|
281
|
+
if (link === null || this.loading || this.titleLink) return;
|
|
255
282
|
|
|
256
283
|
const path = event.composedPath();
|
|
257
284
|
const own = path.slice(0, path.indexOf(this));
|
|
@@ -277,7 +304,7 @@ export class GwCard extends GwElement {
|
|
|
277
304
|
const focus = () => {
|
|
278
305
|
this.#card.classList.toggle(
|
|
279
306
|
"focused",
|
|
280
|
-
this.#link()?.matches(":focus-visible") === true,
|
|
307
|
+
!this.titleLink && this.#link()?.matches(":focus-visible") === true,
|
|
281
308
|
);
|
|
282
309
|
};
|
|
283
310
|
|
|
@@ -327,11 +354,13 @@ export class GwCard extends GwElement {
|
|
|
327
354
|
|
|
328
355
|
const before = animate ? this.offsetHeight : 0;
|
|
329
356
|
|
|
357
|
+
const cardLink = Boolean(this.href) && !this.titleLink;
|
|
358
|
+
|
|
330
359
|
if (
|
|
331
|
-
changed.has("href") &&
|
|
332
|
-
(this.#card.tagName === "A") !==
|
|
360
|
+
(changed.has("href") || changed.has("titleLink")) &&
|
|
361
|
+
(this.#card.tagName === "A") !== cardLink
|
|
333
362
|
) {
|
|
334
|
-
const next =
|
|
363
|
+
const next = cardLink
|
|
335
364
|
? h("a", { class: "card", part: "card" })
|
|
336
365
|
: h("section", { class: "card", part: "card" });
|
|
337
366
|
|
|
@@ -342,11 +371,20 @@ export class GwCard extends GwElement {
|
|
|
342
371
|
|
|
343
372
|
if (this.#card instanceof HTMLAnchorElement) this.#card.href = this.href;
|
|
344
373
|
|
|
374
|
+
setAttribute(
|
|
375
|
+
this.#titleAnchor,
|
|
376
|
+
"href",
|
|
377
|
+
this.titleLink && this.href ? this.href : null,
|
|
378
|
+
);
|
|
379
|
+
|
|
345
380
|
setAttribute(this.#card, "aria-busy", this.loading ? "true" : null);
|
|
346
381
|
|
|
347
382
|
const slotted = this.querySelector(":scope > [slot='heading']") !== null;
|
|
348
383
|
|
|
349
|
-
this.#card.classList.toggle(
|
|
384
|
+
this.#card.classList.toggle(
|
|
385
|
+
"linked",
|
|
386
|
+
this.#link() !== null && !this.href && !this.titleLink,
|
|
387
|
+
);
|
|
350
388
|
this.#title.textContent = this.heading;
|
|
351
389
|
this.#heading.setAttribute("aria-level", String(this.level || 2));
|
|
352
390
|
this.#description.textContent = this.description;
|
package/src/gw-command-menu.ts
CHANGED
|
@@ -23,6 +23,7 @@ const sheetBelow = 600;
|
|
|
23
23
|
* @summary A searchable list of commands on Cmd+K or Ctrl+K.
|
|
24
24
|
*
|
|
25
25
|
* @attr {OptionItem[]} options - The commands, as JSON.
|
|
26
|
+
* @attr {string} value - The current command, such as the page you're on. It's marked, and selected and scrolled into view each time the menu opens.
|
|
26
27
|
* @attr {string} label - The accessible name. Defaults to `Commands`.
|
|
27
28
|
* @attr {string} placeholder - The search placeholder. Defaults to `Search commands`.
|
|
28
29
|
* @attr {string} shortcut - The key that opens it with Cmd or Ctrl, such as `mod+k`, or `none`. Defaults to `mod+k`.
|
|
@@ -37,6 +38,7 @@ const sheetBelow = 600;
|
|
|
37
38
|
export class GwCommandMenu extends GwElement {
|
|
38
39
|
static override properties = {
|
|
39
40
|
options: { type: "json" },
|
|
41
|
+
value: {},
|
|
40
42
|
label: {},
|
|
41
43
|
placeholder: {},
|
|
42
44
|
shortcut: {},
|
|
@@ -154,6 +156,8 @@ export class GwCommandMenu extends GwElement {
|
|
|
154
156
|
];
|
|
155
157
|
|
|
156
158
|
declare options: readonly OptionItem[];
|
|
159
|
+
/** The current command, marked and selected when the menu opens. */
|
|
160
|
+
declare value: string;
|
|
157
161
|
declare label: string;
|
|
158
162
|
declare placeholder: string;
|
|
159
163
|
/** `mod+k` (the default) opens it on Cmd+K or Ctrl+K; `none` turns that off. */
|
|
@@ -178,6 +182,7 @@ export class GwCommandMenu extends GwElement {
|
|
|
178
182
|
constructor() {
|
|
179
183
|
super();
|
|
180
184
|
this.options = [];
|
|
185
|
+
this.value = "";
|
|
181
186
|
this.label = "Commands";
|
|
182
187
|
this.placeholder = "Search commands";
|
|
183
188
|
this.shortcut = "mod+k";
|
|
@@ -268,6 +273,7 @@ export class GwCommandMenu extends GwElement {
|
|
|
268
273
|
const dialog = this.#dialog;
|
|
269
274
|
|
|
270
275
|
list.options = Array.isArray(this.options) ? this.options : [];
|
|
276
|
+
list.value = this.value;
|
|
271
277
|
list.label = this.label;
|
|
272
278
|
list.placeholder = this.placeholder;
|
|
273
279
|
dialog.setAttribute("aria-label", this.label);
|
package/src/gw-dialog.ts
CHANGED
|
@@ -25,6 +25,9 @@ const closeIcon =
|
|
|
25
25
|
* @attr {string} heading - The heading beside the close button.
|
|
26
26
|
* @attr {boolean} open - Whether it shows.
|
|
27
27
|
* @attr {string} close-label - The close button's name, for an app in another language. Defaults to `Close`.
|
|
28
|
+
* @attr {string} discard-question - The question asked before closing with edits, for an app in another language. Defaults to `Discard your changes?`.
|
|
29
|
+
* @attr {string} keep-label - The button that goes back to editing. Defaults to `Keep editing`.
|
|
30
|
+
* @attr {string} discard-label - The button that throws the edits away. Defaults to `Discard`.
|
|
28
31
|
*
|
|
29
32
|
* @slot - The content.
|
|
30
33
|
* @slot actions - Buttons; one with a `value` closes it with that value.
|
|
@@ -42,6 +45,9 @@ export class GwDialog extends GwElement {
|
|
|
42
45
|
heading: {},
|
|
43
46
|
open: { type: "boolean", reflect: true },
|
|
44
47
|
closeLabel: { attribute: "close-label" },
|
|
48
|
+
discardQuestion: { attribute: "discard-question" },
|
|
49
|
+
keepLabel: { attribute: "keep-label" },
|
|
50
|
+
discardLabel: { attribute: "discard-label" },
|
|
45
51
|
} as const;
|
|
46
52
|
|
|
47
53
|
static override styles = [
|
|
@@ -148,6 +154,9 @@ export class GwDialog extends GwElement {
|
|
|
148
154
|
declare open: boolean;
|
|
149
155
|
/** The close button's name, for an app in another language. */
|
|
150
156
|
declare closeLabel: string;
|
|
157
|
+
declare discardQuestion: string;
|
|
158
|
+
declare keepLabel: string;
|
|
159
|
+
declare discardLabel: string;
|
|
151
160
|
|
|
152
161
|
/** The value of the action that closed the dialog, or "" for Esc. */
|
|
153
162
|
returnValue = "";
|
|
@@ -157,6 +166,9 @@ export class GwDialog extends GwElement {
|
|
|
157
166
|
this.heading = "";
|
|
158
167
|
this.open = false;
|
|
159
168
|
this.closeLabel = "Close";
|
|
169
|
+
this.discardQuestion = "Discard your changes?";
|
|
170
|
+
this.keepLabel = "Keep editing";
|
|
171
|
+
this.discardLabel = "Discard";
|
|
160
172
|
}
|
|
161
173
|
|
|
162
174
|
readonly #heading = h("h2", { id: "heading", part: "heading" });
|
|
@@ -251,6 +263,11 @@ export class GwDialog extends GwElement {
|
|
|
251
263
|
|
|
252
264
|
this.#heading.textContent = this.heading;
|
|
253
265
|
this.#closeButton.textContent = this.closeLabel;
|
|
266
|
+
this.#dismissal.text(
|
|
267
|
+
this.discardQuestion,
|
|
268
|
+
this.keepLabel,
|
|
269
|
+
this.discardLabel,
|
|
270
|
+
);
|
|
254
271
|
|
|
255
272
|
if (this.open && !dialog.open) {
|
|
256
273
|
dialog.showModal();
|
package/src/gw-input.ts
CHANGED
|
@@ -34,6 +34,7 @@ const hideIcon =
|
|
|
34
34
|
* @attr {string} min - The lowest value of a `number`, date or time field.
|
|
35
35
|
* @attr {string} max - The highest value of a `number`, date or time field.
|
|
36
36
|
* @attr {string} step - The step between values of a `number`, date or time field, or `any`.
|
|
37
|
+
* @attr {number} maxlength - The most characters it takes.
|
|
37
38
|
* @attr {string} hint - One line of help under the field.
|
|
38
39
|
* @attr {string} info - Longer help, opened from an (i) button by the label.
|
|
39
40
|
* @attr {string} error - An error under the field, which marks it invalid and is announced.
|
|
@@ -63,6 +64,7 @@ export class GwInput extends LightElement {
|
|
|
63
64
|
min: {},
|
|
64
65
|
max: {},
|
|
65
66
|
step: {},
|
|
67
|
+
maxlength: { type: "number" },
|
|
66
68
|
hint: {},
|
|
67
69
|
info: {},
|
|
68
70
|
error: {},
|
|
@@ -92,6 +94,8 @@ export class GwInput extends LightElement {
|
|
|
92
94
|
declare max: string;
|
|
93
95
|
/** The step between values of a number, date or time field. */
|
|
94
96
|
declare step: string;
|
|
97
|
+
/** The most characters it takes, or 0 for no limit. */
|
|
98
|
+
declare maxlength: number;
|
|
95
99
|
declare hint: string;
|
|
96
100
|
/** Longer help, opened from an (i) button by the label. */
|
|
97
101
|
declare info: string;
|
|
@@ -172,6 +176,7 @@ export class GwInput extends LightElement {
|
|
|
172
176
|
this.min = "";
|
|
173
177
|
this.max = "";
|
|
174
178
|
this.step = "";
|
|
179
|
+
this.maxlength = 0;
|
|
175
180
|
this.hint = "";
|
|
176
181
|
this.info = "";
|
|
177
182
|
this.error = "";
|
|
@@ -271,6 +276,11 @@ export class GwInput extends LightElement {
|
|
|
271
276
|
setAttribute(this.#input, "min", this.min || null);
|
|
272
277
|
setAttribute(this.#input, "max", this.max || null);
|
|
273
278
|
setAttribute(this.#input, "step", this.step || null);
|
|
279
|
+
setAttribute(
|
|
280
|
+
control,
|
|
281
|
+
"maxlength",
|
|
282
|
+
this.maxlength > 0 ? String(this.maxlength) : null,
|
|
283
|
+
);
|
|
274
284
|
setAttribute(control, "spellcheck", this.monospace ? "false" : null);
|
|
275
285
|
setAttribute(control, "aria-invalid", this.error ? "true" : null);
|
|
276
286
|
setAttribute(control, "aria-describedby", described || null);
|
package/src/gw-notification.ts
CHANGED
|
@@ -28,6 +28,7 @@ const closeIcon =
|
|
|
28
28
|
* @attr {"neutral"|"accent"|"info"|"success"|"warning"|"danger"|"important"} tone - The icon's color. Defaults to `neutral`.
|
|
29
29
|
* @attr {string} time - When it happened, as shown, such as `2 min ago`.
|
|
30
30
|
* @attr {boolean} unread - Marks it with a stripe until it's seen.
|
|
31
|
+
* @attr {string} dismiss-label - The close button's name, for an app in another language. Defaults to `Dismiss`.
|
|
31
32
|
*
|
|
32
33
|
* @slot - A line of text.
|
|
33
34
|
* @slot actions - Up to two buttons.
|
|
@@ -45,6 +46,7 @@ export class GwNotification extends GwElement {
|
|
|
45
46
|
tone: { reflect: true },
|
|
46
47
|
time: {},
|
|
47
48
|
unread: { type: "boolean", reflect: true },
|
|
49
|
+
dismissLabel: { attribute: "dismiss-label" },
|
|
48
50
|
} as const;
|
|
49
51
|
|
|
50
52
|
static override styles = [
|
|
@@ -64,7 +66,7 @@ export class GwNotification extends GwElement {
|
|
|
64
66
|
color: var(--gw-color-text-primary);
|
|
65
67
|
background: var(--gw-color-surface-raised);
|
|
66
68
|
border: var(--gw-border-width) solid var(--gw-color-border-quiet);
|
|
67
|
-
border-radius: var(--gw-radius-control);
|
|
69
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
/* An inset stripe, so unread and read cards line up */
|
|
@@ -129,6 +131,7 @@ export class GwNotification extends GwElement {
|
|
|
129
131
|
declare tone: Tone;
|
|
130
132
|
declare time: string;
|
|
131
133
|
declare unread: boolean;
|
|
134
|
+
declare dismissLabel: string;
|
|
132
135
|
|
|
133
136
|
readonly #icon = createIcon("");
|
|
134
137
|
|
|
@@ -156,6 +159,7 @@ export class GwNotification extends GwElement {
|
|
|
156
159
|
this.tone = "neutral";
|
|
157
160
|
this.time = "";
|
|
158
161
|
this.unread = false;
|
|
162
|
+
this.dismissLabel = "Dismiss";
|
|
159
163
|
}
|
|
160
164
|
|
|
161
165
|
/** Fires `dismiss`, then folds away and removes itself unless that's cancelled. */
|
|
@@ -212,6 +216,7 @@ export class GwNotification extends GwElement {
|
|
|
212
216
|
this.#heading.textContent = this.heading;
|
|
213
217
|
this.#heading.hidden = !this.heading;
|
|
214
218
|
this.#time.textContent = this.time;
|
|
219
|
+
this.#close.textContent = this.dismissLabel;
|
|
215
220
|
}
|
|
216
221
|
}
|
|
217
222
|
|
package/src/gw-option-list.ts
CHANGED
|
@@ -557,8 +557,10 @@ export class GwOptionList extends GwElement {
|
|
|
557
557
|
const headed =
|
|
558
558
|
previous?.kind === "group" ? (this.#tops[position - 1] ?? top) : top;
|
|
559
559
|
|
|
560
|
+
// A third of the way down, so what's above it shows too without
|
|
561
|
+
// the option sitting at either edge
|
|
560
562
|
if (center) {
|
|
561
|
-
listbox.scrollTop = Math.max(0, top - listbox.clientHeight /
|
|
563
|
+
listbox.scrollTop = Math.max(0, top - listbox.clientHeight / 3);
|
|
562
564
|
} else if (headed - listPadding < listbox.scrollTop) {
|
|
563
565
|
listbox.scrollTop = Math.max(0, headed - listPadding);
|
|
564
566
|
} else if (
|
package/src/gw-popover.ts
CHANGED
|
@@ -35,6 +35,9 @@ const sheetBelow = 600;
|
|
|
35
35
|
* @attr {string} heading - The heading beside the close button.
|
|
36
36
|
* @attr {boolean} confirm - Makes it an `alertdialog`, for a question that needs an answer.
|
|
37
37
|
* @attr {string} close-label - The close button's name, for an app in another language. Defaults to `Close`.
|
|
38
|
+
* @attr {string} discard-question - The question asked before closing with edits, for an app in another language. Defaults to `Discard your changes?`.
|
|
39
|
+
* @attr {string} keep-label - The button that goes back to editing. Defaults to `Keep editing`.
|
|
40
|
+
* @attr {string} discard-label - The button that throws the edits away. Defaults to `Discard`.
|
|
38
41
|
*
|
|
39
42
|
* @slot - The content.
|
|
40
43
|
* @slot actions - Buttons; one with a `value` closes it with that value.
|
|
@@ -53,6 +56,9 @@ export class GwPopover extends GwElement {
|
|
|
53
56
|
heading: {},
|
|
54
57
|
confirm: { type: "boolean" },
|
|
55
58
|
closeLabel: { attribute: "close-label" },
|
|
59
|
+
discardQuestion: { attribute: "discard-question" },
|
|
60
|
+
keepLabel: { attribute: "keep-label" },
|
|
61
|
+
discardLabel: { attribute: "discard-label" },
|
|
56
62
|
} as const;
|
|
57
63
|
|
|
58
64
|
static override styles = [
|
|
@@ -197,6 +203,9 @@ export class GwPopover extends GwElement {
|
|
|
197
203
|
declare confirm: boolean;
|
|
198
204
|
/** The close button's name, for an app in another language. */
|
|
199
205
|
declare closeLabel: string;
|
|
206
|
+
declare discardQuestion: string;
|
|
207
|
+
declare keepLabel: string;
|
|
208
|
+
declare discardLabel: string;
|
|
200
209
|
|
|
201
210
|
/** The value of the action that closed it, or "" for Esc or a click outside. */
|
|
202
211
|
returnValue = "";
|
|
@@ -252,6 +261,9 @@ export class GwPopover extends GwElement {
|
|
|
252
261
|
this.heading = "";
|
|
253
262
|
this.confirm = false;
|
|
254
263
|
this.closeLabel = "Close";
|
|
264
|
+
this.discardQuestion = "Discard your changes?";
|
|
265
|
+
this.keepLabel = "Keep editing";
|
|
266
|
+
this.discardLabel = "Discard";
|
|
255
267
|
}
|
|
256
268
|
|
|
257
269
|
/** Whether its content has changed since it opened, so closing it asks first. */
|
|
@@ -399,6 +411,11 @@ export class GwPopover extends GwElement {
|
|
|
399
411
|
this.#heading.textContent = this.heading;
|
|
400
412
|
this.#heading.hidden = !this.heading;
|
|
401
413
|
this.#closeButton.textContent = this.closeLabel;
|
|
414
|
+
this.#dismissal.text(
|
|
415
|
+
this.discardQuestion,
|
|
416
|
+
this.keepLabel,
|
|
417
|
+
this.discardLabel,
|
|
418
|
+
);
|
|
402
419
|
}
|
|
403
420
|
}
|
|
404
421
|
|
package/src/gw-select.ts
CHANGED
|
@@ -63,6 +63,7 @@ const chevronIcon =
|
|
|
63
63
|
* @attr {boolean} label-hidden - Hides the label but keeps it for assistive technology.
|
|
64
64
|
* @attr {boolean} inline-label - Shows the label inside the trigger, before the value, for toolbars and filters.
|
|
65
65
|
* @attr {"xs"|"small"|"medium"|"large"|"xl"} size - The field's size, 40px tall at medium. Defaults to `medium`.
|
|
66
|
+
* @attr {string} clear-label - The button that clears a multiple choice, for an app in another language. Defaults to `Clear`.
|
|
66
67
|
*
|
|
67
68
|
* @cssprop --gw-field-scale - Scales the field, around 1 for medium.
|
|
68
69
|
* @cssprop --gw-control-scale - Scales its height with the theme's density. The theme sets it.
|
|
@@ -86,6 +87,7 @@ export class GwSelect extends LightElement {
|
|
|
86
87
|
labelHidden: { type: "boolean", attribute: "label-hidden" },
|
|
87
88
|
inlineLabel: { type: "boolean", attribute: "inline-label", reflect: true },
|
|
88
89
|
size: { reflect: true },
|
|
90
|
+
clearLabel: { attribute: "clear-label" },
|
|
89
91
|
} as const;
|
|
90
92
|
|
|
91
93
|
declare label: string;
|
|
@@ -105,6 +107,7 @@ export class GwSelect extends LightElement {
|
|
|
105
107
|
declare labelHidden: boolean;
|
|
106
108
|
declare inlineLabel: boolean;
|
|
107
109
|
declare size: "xs" | "small" | "medium" | "large" | "xl";
|
|
110
|
+
declare clearLabel: string;
|
|
108
111
|
|
|
109
112
|
readonly #id = fieldId();
|
|
110
113
|
|
|
@@ -179,6 +182,7 @@ export class GwSelect extends LightElement {
|
|
|
179
182
|
this.labelHidden = false;
|
|
180
183
|
this.inlineLabel = false;
|
|
181
184
|
this.size = "medium";
|
|
185
|
+
this.clearLabel = "Clear";
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
/** Opens the list, such as from a keyboard shortcut. */
|
|
@@ -439,6 +443,7 @@ export class GwSelect extends LightElement {
|
|
|
439
443
|
: []),
|
|
440
444
|
);
|
|
441
445
|
this.#clear.hidden = !this.multiple || values.length === 0;
|
|
446
|
+
this.#clear.textContent = this.clearLabel;
|
|
442
447
|
|
|
443
448
|
const list = this.#list;
|
|
444
449
|
|
package/src/gw-theme-picker.ts
CHANGED
|
@@ -472,6 +472,15 @@ export class GwThemePicker extends GwElement {
|
|
|
472
472
|
this.#button.addEventListener("click", () => {
|
|
473
473
|
this.show();
|
|
474
474
|
});
|
|
475
|
+
|
|
476
|
+
// A theme or mode applies at once, so it isn't an edit for the popover
|
|
477
|
+
// to ask about discarding, and a click outside still closes it
|
|
478
|
+
for (const type of ["input", "change"]) {
|
|
479
|
+
this.#controls.addEventListener(type, (event) => {
|
|
480
|
+
if (event.target !== this.#controls) event.stopPropagation();
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
475
484
|
this.#mode.addEventListener("change", (event) => {
|
|
476
485
|
event.stopPropagation();
|
|
477
486
|
this.mode = this.#mode.value;
|
package/src/gw-toast.ts
CHANGED
|
@@ -71,7 +71,7 @@ export class GwToaster extends GwElement {
|
|
|
71
71
|
border: var(--gw-border-width) solid var(--gw-color-border-normal);
|
|
72
72
|
border-inline-start: calc(var(--gw-border-width) * 4) solid
|
|
73
73
|
var(--gw-toast-tone);
|
|
74
|
-
border-radius: var(--gw-radius-control);
|
|
74
|
+
border-radius: min(var(--gw-radius-control), var(--gw-radius-panel));
|
|
75
75
|
box-shadow: var(--gw-shadow-m);
|
|
76
76
|
}
|
|
77
77
|
`,
|