vira 31.25.1 → 31.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/pop-up/vira-menu-item.element.d.ts +7 -1
- package/dist/elements/pop-up/vira-menu-item.element.js +38 -32
- package/dist/elements/vira-bold-text.element.js +2 -1
- package/dist/elements/vira-collapsible-card.element.js +2 -1
- package/dist/elements/vira-error.element.js +2 -1
- package/dist/elements/vira-input.element.js +2 -1
- package/dist/elements/vira-json-form.element.d.ts +12 -0
- package/dist/elements/vira-json-form.element.js +104 -3
- package/dist/elements/vira-link.element.js +3 -3
- package/dist/elements/vira-relative-time.element.d.ts +7 -0
- package/dist/elements/vira-relative-time.element.js +8 -1
- package/dist/elements/vira-tabs.element.d.ts +29 -2
- package/dist/elements/vira-tabs.element.js +463 -162
- package/dist/elements/vira-tag.element.js +1 -1
- package/dist/styles/font.d.ts +3 -0
- package/dist/styles/font.js +3 -0
- package/dist/styles/form-styles.d.ts +1 -1
- package/dist/styles/form-styles.js +2 -1
- package/dist/util/vira-json-schema.d.ts +18 -1
- package/dist/util/vira-json-schema.js +37 -1
- package/package.json +1 -1
|
@@ -19,6 +19,12 @@ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefin
|
|
|
19
19
|
* _always_ be shown, even if `selected` is set to `false`.
|
|
20
20
|
*/
|
|
21
21
|
iconOverride: ViraIconSvg;
|
|
22
|
+
/**
|
|
23
|
+
* When `true`, activating this item will _not_ close the containing pop-up.
|
|
24
|
+
*
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
keepOpenAfterInteraction: boolean;
|
|
22
28
|
}>, {
|
|
23
29
|
/** Removes event listeners registered during init. */
|
|
24
30
|
cleanupListeners: undefined | (() => void);
|
|
@@ -29,4 +35,4 @@ export declare const ViraMenuItem: import("element-vir").DeclarativeElementDefin
|
|
|
29
35
|
* gated by `keepOpenAfterInteraction`.
|
|
30
36
|
*/
|
|
31
37
|
activate: import("element-vir").DefineEvent<undefined>;
|
|
32
|
-
}, "vira-menu-item-selected" | "vira-menu-item-disabled" | "vira-menu-item-enabled" | "vira-menu-item-default-icon" | "vira-menu-item-default-styles", "vira-menu-item-", readonly [], readonly []>;
|
|
38
|
+
}, "vira-menu-item-selected" | "vira-menu-item-disabled" | "vira-menu-item-enabled" | "vira-menu-item-default-icon" | "vira-menu-item-default-styles", "vira-menu-item-icon-gap", readonly [], readonly []>;
|
|
@@ -35,14 +35,18 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
35
35
|
'vira-menu-item-default-icon': ({ inputs }) => !inputs.iconOverride,
|
|
36
36
|
'vira-menu-item-default-styles': ({ inputs }) => !inputs.disablePointerStyles,
|
|
37
37
|
},
|
|
38
|
-
|
|
38
|
+
cssVars: {
|
|
39
|
+
/** Horizontal gap between a menu item's icon and its label. */
|
|
40
|
+
'vira-menu-item-icon-gap': '3px',
|
|
41
|
+
},
|
|
42
|
+
styles: ({ hostClasses, cssVars }) => css `
|
|
39
43
|
:host {
|
|
40
44
|
display: flex;
|
|
41
45
|
flex-shrink: 0;
|
|
42
46
|
${noUserSelect};
|
|
43
47
|
box-sizing: border-box;
|
|
44
48
|
max-width: 100%;
|
|
45
|
-
gap:
|
|
49
|
+
gap: ${cssVars['vira-menu-item-icon-gap'].value};
|
|
46
50
|
overflow: hidden;
|
|
47
51
|
padding: 8px 3px;
|
|
48
52
|
padding-right: 16px;
|
|
@@ -119,6 +123,20 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
119
123
|
event.stopPropagation();
|
|
120
124
|
return;
|
|
121
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Only forward `click`. Slotted content is activated by a single forwarded click, so
|
|
128
|
+
* forwarding `mousedown` as well would double-trigger interactions: a `<select>`, for
|
|
129
|
+
* example, opens its picker via `showPicker()` on both `mousedown` and `click`, and the
|
|
130
|
+
* first call consumes the transient user activation so the second throws
|
|
131
|
+
* `NotAllowedError`. `mousedown` still reaches this handler so disabled items can block
|
|
132
|
+
* it above.
|
|
133
|
+
*/
|
|
134
|
+
if (event.type !== 'click') {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (inputs.keepOpenAfterInteraction) {
|
|
138
|
+
event.stopPropagation();
|
|
139
|
+
}
|
|
122
140
|
const slotElement = assertWrap.instanceOf(host.shadowRoot.querySelector('slot'), HTMLSlotElement);
|
|
123
141
|
slotElement
|
|
124
142
|
.assignedElements({
|
|
@@ -129,29 +147,23 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
129
147
|
event.preventDefault();
|
|
130
148
|
event.stopPropagation();
|
|
131
149
|
propagating[event.type] = true;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
element.dispatchEvent(new MouseEvent('click', event));
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
/**
|
|
145
|
-
* Use `.click()` instead of dispatching a synthetic MouseEvent so
|
|
146
|
-
* that the resulting event is trusted and carries user activation.
|
|
147
|
-
* This is required for APIs like `showPicker()` on `<select>`
|
|
148
|
-
* elements.
|
|
149
|
-
*/
|
|
150
|
-
element.click();
|
|
151
|
-
}
|
|
150
|
+
const hasModifiers = event instanceof MouseEvent &&
|
|
151
|
+
(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey);
|
|
152
|
+
if (hasModifiers) {
|
|
153
|
+
/**
|
|
154
|
+
* If modifier keys are present, dispatch a synthetic MouseEvent so that
|
|
155
|
+
* the modifier keys are preserved. This is needed so that cmd+click
|
|
156
|
+
* opens links in a new tab.
|
|
157
|
+
*/
|
|
158
|
+
element.dispatchEvent(new MouseEvent('click', event));
|
|
152
159
|
}
|
|
153
160
|
else {
|
|
154
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Use `.click()` instead of dispatching a synthetic MouseEvent so that
|
|
163
|
+
* the resulting event carries user activation. This is required for
|
|
164
|
+
* APIs like `showPicker()` on `<select>` elements.
|
|
165
|
+
*/
|
|
166
|
+
element.click();
|
|
155
167
|
}
|
|
156
168
|
delete propagating[event.type];
|
|
157
169
|
}
|
|
@@ -160,16 +172,10 @@ export const ViraMenuItem = defineViraElement()({
|
|
|
160
172
|
const listenerRemovers = [
|
|
161
173
|
listenTo(host, 'click', propagateMouseEvent),
|
|
162
174
|
listenTo(host, 'mousedown', propagateMouseEvent),
|
|
163
|
-
/**
|
|
164
|
-
* Emit `select` on a non-disabled activation so the containing pop-up can close. This
|
|
165
|
-
* uses the _capture_ phase because interactive slotted content can stop the click from
|
|
166
|
-
* bubbling back up to this host (which would prevent a bubble-phase listener from ever
|
|
167
|
-
* running). The `propagating` guard skips the synthetic click that
|
|
168
|
-
* `propagateMouseEvent` re-dispatches onto slotted content, so `select` fires exactly
|
|
169
|
-
* once per activation.
|
|
170
|
-
*/
|
|
171
175
|
listenTo(host, 'click', (event) => {
|
|
172
|
-
if (propagating[event.type] ||
|
|
176
|
+
if (propagating[event.type] ||
|
|
177
|
+
inputs.disabled ||
|
|
178
|
+
inputs.keepOpenAfterInteraction) {
|
|
173
179
|
return;
|
|
174
180
|
}
|
|
175
181
|
dispatch(new events.activate(undefined));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { css, html } from 'element-vir';
|
|
2
|
+
import { viraFontCssVars } from '../styles/font.js';
|
|
2
3
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
3
4
|
/**
|
|
4
5
|
* Use this element to reserve space for bolded text, even if it isn't bold yet.
|
|
@@ -8,7 +9,7 @@ import { defineViraElement } from '../util/define-vira-element.js';
|
|
|
8
9
|
export const ViraBoldText = defineViraElement()({
|
|
9
10
|
tagName: 'vira-bold',
|
|
10
11
|
cssVars: {
|
|
11
|
-
'vira-bold-bold-weight': 'bold',
|
|
12
|
+
'vira-bold-bold-weight': viraFontCssVars['vira-font-weight-bold'].value,
|
|
12
13
|
},
|
|
13
14
|
hostClasses: {
|
|
14
15
|
'vira-bold-bold': ({ inputs }) => inputs.bold,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { css, defineElementEvent, html, listen, nothing, testId } from 'element-vir';
|
|
2
2
|
import { ChevronUp16Icon } from '../icons/index.js';
|
|
3
|
+
import { viraFontCssVars } from '../styles/font.js';
|
|
3
4
|
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
4
5
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
5
6
|
import { ViraCollapsibleWrapper } from './vira-collapsible-wrapper.element.js';
|
|
@@ -70,7 +71,7 @@ export const ViraCollapsibleCard = defineViraElement()({
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
.card-header {
|
|
73
|
-
font-weight: bold;
|
|
74
|
+
font-weight: ${viraFontCssVars['vira-font-weight-bold'].value};
|
|
74
75
|
display: flex;
|
|
75
76
|
align-items: center;
|
|
76
77
|
justify-content: space-between;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { css, html } from 'element-vir';
|
|
2
|
+
import { viraFontCssVars } from '../styles/font.js';
|
|
2
3
|
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
3
4
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
4
5
|
/**
|
|
@@ -10,7 +11,7 @@ import { defineViraElement } from '../util/define-vira-element.js';
|
|
|
10
11
|
export const ViraError = defineViraElement()({
|
|
11
12
|
tagName: 'vira-error',
|
|
12
13
|
cssVars: {
|
|
13
|
-
'vira-error-font-weight': 'bold',
|
|
14
|
+
'vira-error-font-weight': viraFontCssVars['vira-font-weight-bold'].value,
|
|
14
15
|
},
|
|
15
16
|
styles: ({ cssVars }) => css `
|
|
16
17
|
:host {
|
|
@@ -5,6 +5,7 @@ import { attributes, css, defineElementEvent, html, ifDefined, listen, nothing,
|
|
|
5
5
|
import { CloseX24Icon } from '../icons/icon-svgs/24/close-x-24.icon.js';
|
|
6
6
|
import { EyeClosed24Icon, EyeOpen24Icon } from '../icons/index.js';
|
|
7
7
|
import { createFocusStyles } from '../styles/focus.js';
|
|
8
|
+
import { viraFontCssVars } from '../styles/font.js';
|
|
8
9
|
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
9
10
|
import { ViraSize, viraSizeHeights } from '../styles/form-variants.js';
|
|
10
11
|
import { noUserSelect, viraAnimationDurations, viraDisabledStyles } from '../styles/index.js';
|
|
@@ -203,7 +204,7 @@ export const ViraInput = defineViraElement()({
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
.suffix {
|
|
206
|
-
font-weight: bold;
|
|
207
|
+
font-weight: ${viraFontCssVars['vira-font-weight-bold'].value};
|
|
207
208
|
${noUserSelect};
|
|
208
209
|
}
|
|
209
210
|
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
2
|
import { type JsonValue } from 'type-fest';
|
|
3
3
|
import { ViraJsonType, type ViraJsonSchema } from '../util/vira-json-schema.js';
|
|
4
|
+
/**
|
|
5
|
+
* Editing mode for a string field that offers both a fixed set of enum options and free-form text.
|
|
6
|
+
*
|
|
7
|
+
* @category Internal
|
|
8
|
+
*/
|
|
9
|
+
export declare enum ViraJsonStringMode {
|
|
10
|
+
/** Pick from the schema's enum options via a dropdown. */
|
|
11
|
+
Options = "options",
|
|
12
|
+
/** Enter an arbitrary string via a text input. */
|
|
13
|
+
Custom = "custom"
|
|
14
|
+
}
|
|
4
15
|
/**
|
|
5
16
|
* An editor for arbitrary JSON values, optionally constrained by a standard JSON Schema
|
|
6
17
|
* ({@link ViraJsonSchema}).
|
|
@@ -16,6 +27,7 @@ export declare const ViraJsonForm: import("element-vir").DeclarativeElementDefin
|
|
|
16
27
|
pendingKeys: Readonly<Record<string, string>>;
|
|
17
28
|
pendingTypes: Readonly<Record<string, ViraJsonType>>;
|
|
18
29
|
pendingArrayValues: Readonly<Record<string, JsonValue>>;
|
|
30
|
+
stringModes: Readonly<Record<string, ViraJsonStringMode>>;
|
|
19
31
|
showRaw: boolean;
|
|
20
32
|
rawDraft: string | undefined;
|
|
21
33
|
rawError: string | undefined;
|
|
@@ -6,13 +6,25 @@ import { viraFontCssVars } from '../styles/font.js';
|
|
|
6
6
|
import { viraFormCssVars } from '../styles/form-styles.js';
|
|
7
7
|
import { ViraColorVariant, ViraEmphasis, ViraSize } from '../styles/form-variants.js';
|
|
8
8
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
9
|
-
import { createDefaultForJsonType, createResolveContext, deleteValueAtPath, getAdditionalPropertiesSchema, getAllowedJsonTypes, getDefinedProperties,
|
|
9
|
+
import { allowsFreeformString, createDefaultForJsonType, createResolveContext, deleteValueAtPath, getAdditionalPropertiesSchema, getAllowedJsonTypes, getDefinedProperties, getItemSchema, getJsonType, getNewItemSchema, getPropertySchema, getRequiredProperties, getSchemaEnumValues, getSchemaTitle, getStringEnumValues, pathToKey, pickBranchForType, setValueAtPath, validateAgainstSchema, ViraJsonType, viraJsonTypeLabels, } from '../util/vira-json-schema.js';
|
|
10
10
|
import { ViraButton } from './vira-button.element.js';
|
|
11
11
|
import { ViraCheckbox } from './vira-checkbox.element.js';
|
|
12
12
|
import { ViraError } from './vira-error.element.js';
|
|
13
13
|
import { ViraInput, ViraInputType } from './vira-input.element.js';
|
|
14
14
|
import { ViraSelect } from './vira-select.element.js';
|
|
15
15
|
import { ViraTextArea } from './vira-text-area.element.js';
|
|
16
|
+
/**
|
|
17
|
+
* Editing mode for a string field that offers both a fixed set of enum options and free-form text.
|
|
18
|
+
*
|
|
19
|
+
* @category Internal
|
|
20
|
+
*/
|
|
21
|
+
export var ViraJsonStringMode;
|
|
22
|
+
(function (ViraJsonStringMode) {
|
|
23
|
+
/** Pick from the schema's enum options via a dropdown. */
|
|
24
|
+
ViraJsonStringMode["Options"] = "options";
|
|
25
|
+
/** Enter an arbitrary string via a text input. */
|
|
26
|
+
ViraJsonStringMode["Custom"] = "custom";
|
|
27
|
+
})(ViraJsonStringMode || (ViraJsonStringMode = {}));
|
|
16
28
|
/**
|
|
17
29
|
* An editor for arbitrary JSON values, optionally constrained by a standard JSON Schema
|
|
18
30
|
* ({@link ViraJsonSchema}).
|
|
@@ -29,6 +41,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
29
41
|
pendingKeys: {},
|
|
30
42
|
pendingTypes: {},
|
|
31
43
|
pendingArrayValues: {},
|
|
44
|
+
stringModes: {},
|
|
32
45
|
showRaw: false,
|
|
33
46
|
rawDraft: undefined,
|
|
34
47
|
rawError: undefined,
|
|
@@ -129,7 +142,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
129
142
|
}
|
|
130
143
|
|
|
131
144
|
.json-type-tag {
|
|
132
|
-
font-weight: normal;
|
|
145
|
+
font-weight: ${viraFontCssVars['vira-font-weight-normal'].value};
|
|
133
146
|
color: ${viraFormCssVars['vira-form-secondary-body-foreground'].value};
|
|
134
147
|
}
|
|
135
148
|
|
|
@@ -238,6 +251,23 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
238
251
|
},
|
|
239
252
|
});
|
|
240
253
|
}
|
|
254
|
+
function getStringMode(pathKey, value, enumValues) {
|
|
255
|
+
const stored = state.stringModes[pathKey];
|
|
256
|
+
if (stored) {
|
|
257
|
+
return stored;
|
|
258
|
+
}
|
|
259
|
+
return enumValues.includes(value)
|
|
260
|
+
? ViraJsonStringMode.Options
|
|
261
|
+
: ViraJsonStringMode.Custom;
|
|
262
|
+
}
|
|
263
|
+
function setStringMode(pathKey, mode) {
|
|
264
|
+
updateState({
|
|
265
|
+
stringModes: {
|
|
266
|
+
...state.stringModes,
|
|
267
|
+
[pathKey]: mode,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
}
|
|
241
271
|
function clearPending(pathKey) {
|
|
242
272
|
updateState({
|
|
243
273
|
pendingKeys: omitObjectKeys(state.pendingKeys, [pathKey]),
|
|
@@ -260,7 +290,7 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
260
290
|
}
|
|
261
291
|
function renderPrimitive(path, value, schema) {
|
|
262
292
|
const type = getJsonType(value);
|
|
263
|
-
const enumValues =
|
|
293
|
+
const enumValues = getSchemaEnumValues(schema, resolveContext);
|
|
264
294
|
if (enumValues && enumValues.length > 0) {
|
|
265
295
|
const options = enumValues.map((entry) => {
|
|
266
296
|
const asString = jsonPrimitiveToString(entry);
|
|
@@ -734,6 +764,64 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
734
764
|
</table>
|
|
735
765
|
`;
|
|
736
766
|
}
|
|
767
|
+
function renderStringEnumOrRaw(path, value, enumValues) {
|
|
768
|
+
const pathKey = pathToKey(path);
|
|
769
|
+
const mode = getStringMode(pathKey, value, enumValues);
|
|
770
|
+
const editor = mode === ViraJsonStringMode.Options
|
|
771
|
+
? html `
|
|
772
|
+
<${ViraSelect.assign({
|
|
773
|
+
options: enumValues.map((entry) => {
|
|
774
|
+
return {
|
|
775
|
+
value: entry,
|
|
776
|
+
label: entry,
|
|
777
|
+
};
|
|
778
|
+
}),
|
|
779
|
+
value: enumValues.includes(value) ? value : undefined,
|
|
780
|
+
disabled: isDisabled,
|
|
781
|
+
})}
|
|
782
|
+
${listen(ViraSelect.events.valueChange, (event) => {
|
|
783
|
+
emitReplaceAt(path, event.detail);
|
|
784
|
+
})}
|
|
785
|
+
></${ViraSelect}>
|
|
786
|
+
`
|
|
787
|
+
: html `
|
|
788
|
+
<${ViraInput.assign({
|
|
789
|
+
value,
|
|
790
|
+
disabled: isDisabled,
|
|
791
|
+
})}
|
|
792
|
+
${listen(ViraInput.events.valueChange, (event) => {
|
|
793
|
+
emitReplaceAt(path, event.detail);
|
|
794
|
+
})}
|
|
795
|
+
></${ViraInput}>
|
|
796
|
+
`;
|
|
797
|
+
if (isDisabled) {
|
|
798
|
+
return editor;
|
|
799
|
+
}
|
|
800
|
+
const modeOptions = [
|
|
801
|
+
{
|
|
802
|
+
value: ViraJsonStringMode.Options,
|
|
803
|
+
label: 'Options',
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
value: ViraJsonStringMode.Custom,
|
|
807
|
+
label: 'Custom',
|
|
808
|
+
},
|
|
809
|
+
];
|
|
810
|
+
return html `
|
|
811
|
+
<div class="json-value-with-switcher">
|
|
812
|
+
<span class="json-value-editor-slot">${editor}</span>
|
|
813
|
+
<${ViraSelect.assign({
|
|
814
|
+
options: modeOptions,
|
|
815
|
+
value: mode,
|
|
816
|
+
})}
|
|
817
|
+
title="Choose from options or enter a custom value"
|
|
818
|
+
${listen(ViraSelect.events.valueChange, (event) => {
|
|
819
|
+
setStringMode(pathKey, event.detail);
|
|
820
|
+
})}
|
|
821
|
+
></${ViraSelect}>
|
|
822
|
+
</div>
|
|
823
|
+
`;
|
|
824
|
+
}
|
|
737
825
|
function renderValue(path, value, schema) {
|
|
738
826
|
const concreteType = getJsonType(value);
|
|
739
827
|
const allowedTypes = getAllowedJsonTypes(schema, resolveContext);
|
|
@@ -744,6 +832,19 @@ export const ViraJsonForm = defineViraElement()({
|
|
|
744
832
|
else if (check.isObject(value)) {
|
|
745
833
|
return renderObjectGroup(path, value, narrowedSchema);
|
|
746
834
|
}
|
|
835
|
+
/**
|
|
836
|
+
* When a string field constrains values to an enum but also permits free-form strings,
|
|
837
|
+
* offer both: an options dropdown plus a switcher to toggle to raw text entry.
|
|
838
|
+
*/
|
|
839
|
+
const isStringOnlyField = allowedTypes.length === 1 && allowedTypes[0] === ViraJsonType.String;
|
|
840
|
+
const stringEnumValues = isStringOnlyField
|
|
841
|
+
? getStringEnumValues(schema, resolveContext)
|
|
842
|
+
: [];
|
|
843
|
+
if (check.isString(value) &&
|
|
844
|
+
stringEnumValues.length > 0 &&
|
|
845
|
+
allowsFreeformString(schema, resolveContext)) {
|
|
846
|
+
return renderStringEnumOrRaw(path, value, stringEnumValues);
|
|
847
|
+
}
|
|
747
848
|
const editor = renderPrimitive(path, value, narrowedSchema);
|
|
748
849
|
const showSwitcher = !isDisabled &&
|
|
749
850
|
allowedTypes.length > 1 &&
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assertWrap } from '@augment-vir/assert';
|
|
2
2
|
import { attributes, css, html, ifDefined, listen, } from 'element-vir';
|
|
3
3
|
import { listenTo } from 'typed-event-target';
|
|
4
|
-
import {
|
|
4
|
+
import { viraTheme } from '../styles/vira-color-theme.js';
|
|
5
5
|
import { defineViraElement } from '../util/define-vira-element.js';
|
|
6
6
|
/**
|
|
7
7
|
* A hyperlink wrapper element that can be configured to emit route change events rather than just
|
|
@@ -41,12 +41,12 @@ export const ViraLink = defineViraElement()({
|
|
|
41
41
|
${hostClasses['vira-link-link-styles'].selector} {
|
|
42
42
|
&:hover a,
|
|
43
43
|
& a:hover {
|
|
44
|
-
color: ${
|
|
44
|
+
color: ${viraTheme.colors['vira-blue-foreground-non-body'].foreground.value};
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
&:active a,
|
|
48
48
|
& a:active {
|
|
49
|
-
color: ${
|
|
49
|
+
color: ${viraTheme.colors['vira-blue-foreground-body'].foreground.value};
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
`,
|
|
@@ -20,6 +20,13 @@ export declare const ViraRelativeTime: import("element-vir").DeclarativeElementD
|
|
|
20
20
|
* @default {seconds: 5}
|
|
21
21
|
*/
|
|
22
22
|
updateInterval: Readonly<AtLeastOneDuration>;
|
|
23
|
+
/**
|
|
24
|
+
* Timezone the absolute time is displayed in. Defaults to the user's timezone. Set this for
|
|
25
|
+
* values that are conceptually anchored to a specific timezone (e.g. a date-only value
|
|
26
|
+
* stored at midnight UTC), where converting to the user's timezone would shift the
|
|
27
|
+
* displayed date/time.
|
|
28
|
+
*/
|
|
29
|
+
timezone: string;
|
|
23
30
|
}>, {
|
|
24
31
|
now: {
|
|
25
32
|
hour: import("date-vir").Hour;
|
|
@@ -76,11 +76,18 @@ export const ViraRelativeTime = defineViraElement()({
|
|
|
76
76
|
decimalCount: 0,
|
|
77
77
|
});
|
|
78
78
|
return html `
|
|
79
|
-
<span
|
|
79
|
+
<span
|
|
80
|
+
title=${formatAbsoluteTime(inputs.time, {
|
|
81
|
+
timezone: inputs.timezone,
|
|
82
|
+
})}
|
|
83
|
+
>
|
|
84
|
+
${relativeTime}
|
|
85
|
+
</span>
|
|
80
86
|
${inputs.showAbsoluteTime
|
|
81
87
|
? html `
|
|
82
88
|
<${ViraAbsoluteTime.assign({
|
|
83
89
|
time: inputs.time,
|
|
90
|
+
timezone: inputs.timezone,
|
|
84
91
|
})}></${ViraAbsoluteTime}>
|
|
85
92
|
`
|
|
86
93
|
: nothing}
|
|
@@ -44,7 +44,25 @@ export type ViraTab = {
|
|
|
44
44
|
* current route.
|
|
45
45
|
*/
|
|
46
46
|
exactMatch: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Optional cluster label. Consecutive tabs sharing the same `group` string render together
|
|
49
|
+
* under that label, separated from other clusters by an inset vertical divider. Tabs with no
|
|
50
|
+
* `group` render standalone (no label, no divider). Grouping only affects rendering when at
|
|
51
|
+
* least one tab has a `group`.
|
|
52
|
+
*/
|
|
53
|
+
group: string;
|
|
47
54
|
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Groups a flat list of tabs into clusters. Consecutive tabs sharing the same `group` string are
|
|
57
|
+
* merged into a single cluster; ungrouped tabs (and tabs whose `group` differs from their
|
|
58
|
+
* predecessor) each start a new cluster.
|
|
59
|
+
*
|
|
60
|
+
* @category Internal
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildClusters(tabList: ReadonlyArray<Readonly<ViraTab>>): {
|
|
63
|
+
group: string | undefined;
|
|
64
|
+
tabs: ReadonlyArray<Readonly<ViraTab>>;
|
|
65
|
+
}[];
|
|
48
66
|
/**
|
|
49
67
|
* A tab bar element that renders an array of tabs with an animated selection indicator.
|
|
50
68
|
*
|
|
@@ -85,13 +103,22 @@ export declare const ViraTabs: import("element-vir").DeclarativeElementDefinitio
|
|
|
85
103
|
menuIsDisabled: boolean;
|
|
86
104
|
/** Offset for the dropdown pop-up. Only used when tabs overflow into a dropdown. */
|
|
87
105
|
menuPopUpOffset: Readonly<PopUpOffset>;
|
|
106
|
+
/**
|
|
107
|
+
* Text shown on the overflow "more" trigger when the selected tab is _not_ collapsed into
|
|
108
|
+
* the menu. When the selected tab _is_ collapsed, the trigger shows that tab's label (with
|
|
109
|
+
* a checkmark) instead. Set this to a localized string; it defaults to `'More'`.
|
|
110
|
+
*
|
|
111
|
+
* @default 'More'
|
|
112
|
+
*/
|
|
113
|
+
overflowLabel: string;
|
|
88
114
|
/** When true, tabs and their container expand to fill all available horizontal space. */
|
|
89
115
|
shouldFillWidth: boolean;
|
|
90
116
|
}>, {
|
|
91
|
-
|
|
117
|
+
/** How many of the visible tabs are collapsed into the overflow "more" menu. */
|
|
118
|
+
overflowCount: number;
|
|
92
119
|
/** A callback to remove all internal observers. */
|
|
93
120
|
cleanupObserver: undefined | (() => void);
|
|
94
121
|
}, {
|
|
95
122
|
/** Fires when a tab is clicked with the corresponding tab entry. */
|
|
96
123
|
tabSelect: import("element-vir").DefineEvent<Readonly<ViraTab>>;
|
|
97
|
-
}, "vira-tabs-bar-top" | "vira-tabs-bar-bottom" | "vira-tabs-bar-left" | "vira-tabs-bar-right" | "vira-tabs-color-red" | "vira-tabs-color-yellow" | "vira-tabs-color-green" | "vira-tabs-color-blue" | "vira-tabs-color-brand" | "vira-tabs-color-purple" | "vira-tabs-color-plain" | "vira-tabs-color-neutral" | "vira-tabs-color-teal" | "vira-tabs-color-pink" | "vira-tabs-color-grey" | "vira-tabs-icon-layout-vertical" | "vira-tabs-icon-layout-horizontal" | "vira-tabs-
|
|
124
|
+
}, "vira-tabs-bar-top" | "vira-tabs-bar-bottom" | "vira-tabs-bar-left" | "vira-tabs-bar-right" | "vira-tabs-color-red" | "vira-tabs-color-yellow" | "vira-tabs-color-green" | "vira-tabs-color-blue" | "vira-tabs-color-brand" | "vira-tabs-color-purple" | "vira-tabs-color-plain" | "vira-tabs-color-neutral" | "vira-tabs-color-teal" | "vira-tabs-color-pink" | "vira-tabs-color-grey" | "vira-tabs-icon-layout-vertical" | "vira-tabs-icon-layout-horizontal" | "vira-tabs-fill-width", "vira-tabs-active-color" | "vira-tabs-active-hover-color" | "vira-tabs-inactive-color" | "vira-tabs-inactive-hover-color" | "vira-tabs-bar-thickness", readonly [], readonly []>;
|