@astronox/core 0.2.1 → 0.2.3
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/package.json +7 -1
- package/src/admin/cache.ts +217 -0
- package/src/admin/contracts.ts +28 -0
- package/src/admin/index.ts +3 -0
- package/src/admin/module.ts +28 -0
- package/src/auth/contracts.ts +53 -0
- package/src/auth/firebase/client.ts +83 -0
- package/src/auth/firebase/contracts.ts +8 -0
- package/src/auth/firebase/index.ts +1 -0
- package/src/auth/index.ts +2 -0
- package/src/auth/module.ts +99 -0
- package/src/client/formSubmission.ts +177 -0
- package/src/client/index.ts +4 -0
- package/src/client/preferences.ts +400 -0
- package/src/components/actions/Button/Button.astro +42 -6
- package/src/components/actions/Button/Button.css +19 -0
- package/src/components/actions/IdentityProviderAction/IdentityProviderAction.astro +35 -0
- package/src/components/actions/ScrollToTop/ScrollToTop.css +11 -0
- package/src/components/content/CardBody/CardBody.astro +3 -0
- package/src/components/content/CardBody/CardBody.css +16 -2
- package/src/components/content/CardFooter/CardFooter.astro +9 -0
- package/src/components/content/CardFooter/CardFooter.css +45 -3
- package/src/components/content/CardLink/CardLink.astro +12 -3
- package/src/components/content/CardLink/CardLink.css +32 -0
- package/src/components/content/MarkdownContent/MarkdownContent.css +14 -4
- package/src/components/content/MarkdownContent/MarkdownInline.astro +1 -1
- package/src/components/content/MarkdownContent/contracts.ts +1 -1
- package/src/components/content/MarkdownContent/markdownContentRenderer.ts +552 -0
- package/src/components/data-display/TextPair/TextPair.css +8 -2
- package/src/components/feedback/PreferenceBootstrap/PreferenceBootstrap.astro +403 -0
- package/src/components/forms/Checkbox/Checkbox.astro +6 -0
- package/src/components/forms/ChoiceGroup/ChoiceGroup.astro +57 -0
- package/src/components/forms/ChoiceGroup/ChoiceGroup.css +108 -0
- package/src/components/forms/ChoiceGroup/contracts.ts +9 -0
- package/src/components/forms/DateTimeInput/DateTimeInput.astro +14 -0
- package/src/components/forms/PreparedFormBootstrap/PreparedFormBootstrap.astro +203 -0
- package/src/components/forms/PreparedFormBootstrap/contracts.ts +15 -0
- package/src/components/forms/TextInput/TextInput.astro +7 -1
- package/src/components/forms/Textarea/Textarea.astro +35 -0
- package/src/components/forms/Textarea/Textarea.css +62 -0
- package/src/components/icons/BackIcon.astro +26 -0
- package/src/components/icons/DeleteIcon.astro +22 -0
- package/src/components/icons/StatusIndicatorIcon.astro +16 -0
- package/src/components/index.ts +18 -0
- package/src/components/media/CanvasFrame/CanvasFrame.astro +1 -17
- package/src/components/media/EmbedFrame/EmbedFrame.astro +1 -19
- package/src/components/media/EmbedFrame/EmbedFrame.css +0 -2
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.astro +5 -1
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.css +12 -17
- package/src/components/navigation/Footer/Footer.astro +102 -0
- package/src/components/navigation/Footer/Footer.css +155 -0
- package/src/components/navigation/Footer/contracts.ts +17 -0
- package/src/components/navigation/SubNavigation/SubNavigation.css +0 -5
- package/src/composition/Grid/Grid.css +16 -0
- package/src/composition/SurfaceGroup/SurfaceGroup.css +21 -7
- package/src/composition/SurfaceGroup/stickySurfaceGroupController.ts +3 -0
- package/src/data/firestore/client/contracts.ts +78 -0
- package/src/data/firestore/client/firebase.ts +56 -0
- package/src/data/firestore/client/index.ts +3 -0
- package/src/data/firestore/client/repository.ts +111 -0
- package/src/display/contracts.ts +44 -1
- package/src/display/index.ts +1 -0
- package/src/display/tableProgressive.ts +62 -0
- package/src/layouts/BaseLayout.astro +8 -1
- package/src/patterns/Combobox/Combobox.astro +23 -0
- package/src/patterns/Combobox/comboboxController.ts +69 -0
- package/src/patterns/Fullscreen/FullscreenControl.astro +4 -14
- package/src/patterns/Fullscreen/FullscreenControl.css +0 -26
- package/src/patterns/Modal/Modal.astro +1 -1
- package/src/patterns/Modal/Modal.css +38 -1
- package/src/patterns/Table/Table.astro +122 -7
- package/src/patterns/Table/TableBody.astro +8 -0
- package/src/patterns/Table/TableBody.css +3 -3
- package/src/patterns/Table/TableCell.css +11 -1
- package/src/patterns/Table/TableCellValue.astro +31 -0
- package/src/patterns/Table/TableFooter.astro +3 -1
- package/src/patterns/Table/TableHeader.astro +1 -0
- package/src/patterns/Table/TablePagination.astro +63 -47
- package/src/patterns/Table/TableSkeleton.astro +18 -22
- package/src/patterns/Table/TableSkeleton.css +30 -5
- package/src/patterns/Table/tableClientController.ts +253 -0
- package/src/patterns/Table/tableFilterController.ts +23 -31
- package/src/patterns/Table/tableProgressiveController.ts +615 -227
- package/src/patterns/Table/tableSortController.ts +25 -7
- package/src/styles/base.css +24 -7
- package/src/styles/interaction.css +16 -0
- package/src/styles/style.css +3 -0
- package/src/styles/tokens.css +5 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
type Props = {
|
|
3
|
+
formId: string;
|
|
4
|
+
stateKey: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const { formId, stateKey }: Props = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<script is:inline define:vars={{ formId, stateKey }}>
|
|
11
|
+
(() => {
|
|
12
|
+
const isRecord = (value) =>
|
|
13
|
+
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
const readState = () => {
|
|
15
|
+
const state = window[stateKey];
|
|
16
|
+
return isRecord(state) ? state : null;
|
|
17
|
+
};
|
|
18
|
+
const createTag = (value, label) => {
|
|
19
|
+
const tag = document.createElement('span');
|
|
20
|
+
tag.className = 'tag';
|
|
21
|
+
tag.dataset.widget = 'tag';
|
|
22
|
+
tag.dataset.size = 'sm';
|
|
23
|
+
tag.dataset.comboboxTag = value;
|
|
24
|
+
const tagLabel = document.createElement('span');
|
|
25
|
+
tagLabel.className = 'tag__label';
|
|
26
|
+
tagLabel.dataset.tagLabel = '';
|
|
27
|
+
tagLabel.textContent = label;
|
|
28
|
+
tag.append(tagLabel);
|
|
29
|
+
return tag;
|
|
30
|
+
};
|
|
31
|
+
const getNamedFields = (form, name) => {
|
|
32
|
+
const item = form.elements.namedItem(name);
|
|
33
|
+
if (item instanceof RadioNodeList) return [...item];
|
|
34
|
+
return item ? [item] : [];
|
|
35
|
+
};
|
|
36
|
+
const getComboboxRoot = (form, key) =>
|
|
37
|
+
[...form.querySelectorAll('[data-prepared-form-combobox]')]
|
|
38
|
+
.find((candidate) => candidate.dataset.preparedFormCombobox === key);
|
|
39
|
+
const isComboboxReady = (root) =>
|
|
40
|
+
root instanceof HTMLElement &&
|
|
41
|
+
root.querySelector('[data-combobox-options]') instanceof HTMLElement &&
|
|
42
|
+
root.querySelector('[data-combobox-empty]') instanceof HTMLElement &&
|
|
43
|
+
root.querySelector('[data-combobox-values]') instanceof HTMLElement &&
|
|
44
|
+
root.querySelector('[data-combobox-placeholder]') instanceof HTMLElement;
|
|
45
|
+
const isFormReady = (form, state) => {
|
|
46
|
+
if (isRecord(state.values)) {
|
|
47
|
+
for (const name of Object.keys(state.values)) {
|
|
48
|
+
if (getNamedFields(form, name).length === 0) return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (isRecord(state.choices)) {
|
|
52
|
+
for (const [name, value] of Object.entries(state.choices)) {
|
|
53
|
+
if (
|
|
54
|
+
typeof value !== 'string' ||
|
|
55
|
+
!getNamedFields(form, name).some(
|
|
56
|
+
(field) =>
|
|
57
|
+
field instanceof HTMLInputElement && field.value === value,
|
|
58
|
+
)
|
|
59
|
+
) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (isRecord(state.comboboxes)) {
|
|
65
|
+
for (const key of Object.keys(state.comboboxes)) {
|
|
66
|
+
if (!isComboboxReady(getComboboxRoot(form, key))) return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
};
|
|
71
|
+
const applyCombobox = (form, key, state) => {
|
|
72
|
+
if (!isRecord(state) || !Array.isArray(state.options)) return;
|
|
73
|
+
const root = getComboboxRoot(form, key);
|
|
74
|
+
if (!(root instanceof HTMLElement)) return;
|
|
75
|
+
const optionsRoot = root.querySelector('[data-combobox-options]');
|
|
76
|
+
const empty = root.querySelector('[data-combobox-empty]');
|
|
77
|
+
const valuesRoot = root.querySelector('[data-combobox-values]');
|
|
78
|
+
const placeholder = root.querySelector('[data-combobox-placeholder]');
|
|
79
|
+
if (
|
|
80
|
+
!(optionsRoot instanceof HTMLElement) ||
|
|
81
|
+
!(empty instanceof HTMLElement) ||
|
|
82
|
+
!(valuesRoot instanceof HTMLElement) ||
|
|
83
|
+
!(placeholder instanceof HTMLElement)
|
|
84
|
+
) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
optionsRoot
|
|
89
|
+
.querySelectorAll('[data-combobox-option]')
|
|
90
|
+
.forEach((node) => node.remove());
|
|
91
|
+
root
|
|
92
|
+
.querySelectorAll('template[data-combobox-tag-template]')
|
|
93
|
+
.forEach((node) => node.remove());
|
|
94
|
+
const options = state.options.filter(
|
|
95
|
+
(option) =>
|
|
96
|
+
isRecord(option) &&
|
|
97
|
+
typeof option.label === 'string' &&
|
|
98
|
+
typeof option.value === 'string',
|
|
99
|
+
);
|
|
100
|
+
const selected = new Set(
|
|
101
|
+
Array.isArray(state.values)
|
|
102
|
+
? state.values.filter((value) => typeof value === 'string')
|
|
103
|
+
: [],
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
options.forEach((option, index) => {
|
|
107
|
+
const button = document.createElement('button');
|
|
108
|
+
button.className = 'combobox__option';
|
|
109
|
+
button.id = `${root.id || key}-option-${index}`;
|
|
110
|
+
button.type = 'button';
|
|
111
|
+
button.role = 'option';
|
|
112
|
+
button.tabIndex = -1;
|
|
113
|
+
button.setAttribute('aria-selected', String(selected.has(option.value)));
|
|
114
|
+
button.dataset.comboboxOption = option.value;
|
|
115
|
+
button.dataset.comboboxSearchText = option.label;
|
|
116
|
+
button.dataset.interactionAccent = 'start';
|
|
117
|
+
const content = document.createElement('span');
|
|
118
|
+
content.className = 'combobox__option-content';
|
|
119
|
+
const label = document.createElement('span');
|
|
120
|
+
label.className = 'combobox__option-label';
|
|
121
|
+
label.textContent = option.label;
|
|
122
|
+
content.append(label);
|
|
123
|
+
button.append(content);
|
|
124
|
+
optionsRoot.insertBefore(button, empty);
|
|
125
|
+
|
|
126
|
+
const template = document.createElement('template');
|
|
127
|
+
template.dataset.comboboxTagTemplate = option.value;
|
|
128
|
+
template.content.append(createTag(option.value, option.label));
|
|
129
|
+
root.append(template);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
valuesRoot
|
|
133
|
+
.querySelectorAll('[data-combobox-tag]')
|
|
134
|
+
.forEach((node) => node.remove());
|
|
135
|
+
for (const value of selected) {
|
|
136
|
+
const option = options.find((candidate) => candidate.value === value);
|
|
137
|
+
if (option) {
|
|
138
|
+
valuesRoot.insertBefore(createTag(value, option.label), placeholder);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
placeholder.hidden = selected.size > 0;
|
|
142
|
+
empty.hidden = options.length > 0;
|
|
143
|
+
};
|
|
144
|
+
const apply = () => {
|
|
145
|
+
const form = document.getElementById(formId);
|
|
146
|
+
const state = readState();
|
|
147
|
+
if (
|
|
148
|
+
!(form instanceof HTMLFormElement) ||
|
|
149
|
+
!state ||
|
|
150
|
+
!isFormReady(form, state)
|
|
151
|
+
) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (isRecord(state.values)) {
|
|
156
|
+
for (const [name, value] of Object.entries(state.values)) {
|
|
157
|
+
if (typeof value !== 'string') continue;
|
|
158
|
+
for (const field of getNamedFields(form, name)) {
|
|
159
|
+
if (
|
|
160
|
+
field instanceof HTMLInputElement ||
|
|
161
|
+
field instanceof HTMLTextAreaElement ||
|
|
162
|
+
field instanceof HTMLSelectElement
|
|
163
|
+
) {
|
|
164
|
+
field.value = value;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (isRecord(state.choices)) {
|
|
170
|
+
for (const [name, value] of Object.entries(state.choices)) {
|
|
171
|
+
if (typeof value !== 'string') continue;
|
|
172
|
+
for (const field of getNamedFields(form, name)) {
|
|
173
|
+
if (field instanceof HTMLInputElement) {
|
|
174
|
+
field.checked = field.value === value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (isRecord(state.comboboxes)) {
|
|
180
|
+
for (const [key, combobox] of Object.entries(state.comboboxes)) {
|
|
181
|
+
applyCombobox(form, key, combobox);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
form.dataset.preparedFormBootstrap = 'true';
|
|
185
|
+
return true;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
if (apply()) return;
|
|
189
|
+
const observer = new MutationObserver(() => {
|
|
190
|
+
if (!apply()) return;
|
|
191
|
+
observer.disconnect();
|
|
192
|
+
});
|
|
193
|
+
observer.observe(document.documentElement, {
|
|
194
|
+
childList: true,
|
|
195
|
+
subtree: true,
|
|
196
|
+
});
|
|
197
|
+
document.addEventListener(
|
|
198
|
+
'DOMContentLoaded',
|
|
199
|
+
() => observer.disconnect(),
|
|
200
|
+
{ once: true },
|
|
201
|
+
);
|
|
202
|
+
})();
|
|
203
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type PreparedFormOption = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type PreparedFormCombobox = {
|
|
7
|
+
options: readonly PreparedFormOption[];
|
|
8
|
+
values: readonly string[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type PreparedFormState = {
|
|
12
|
+
choices?: Readonly<Record<string, string>>;
|
|
13
|
+
comboboxes?: Readonly<Record<string, PreparedFormCombobox>>;
|
|
14
|
+
values?: Readonly<Record<string, string>>;
|
|
15
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
import type { PreferenceBinding } from '../../../client/preferences';
|
|
3
4
|
import type { Tone } from '../../../theme/contracts';
|
|
4
5
|
import CloseIcon from '../../icons/CloseIcon.astro';
|
|
5
6
|
|
|
6
7
|
type TextInputFraming = 'embedded' | 'standalone';
|
|
7
|
-
type TextInputType = 'search' | 'text';
|
|
8
|
+
type TextInputType = 'datetime-local' | 'search' | 'text';
|
|
8
9
|
type TextInputAutofocus = boolean | 'desktop';
|
|
9
10
|
|
|
10
11
|
type Props = Omit<HTMLAttributes<'input'>, 'autofocus' | 'type'> & {
|
|
@@ -13,6 +14,7 @@ type Props = Omit<HTMLAttributes<'input'>, 'autofocus' | 'type'> & {
|
|
|
13
14
|
clearLabel?: string;
|
|
14
15
|
framing?: TextInputFraming;
|
|
15
16
|
invalid?: boolean;
|
|
17
|
+
preference?: PreferenceBinding;
|
|
16
18
|
tone?: Tone;
|
|
17
19
|
type?: TextInputType;
|
|
18
20
|
};
|
|
@@ -26,6 +28,7 @@ const {
|
|
|
26
28
|
'data-tone': dataTone,
|
|
27
29
|
framing = 'standalone',
|
|
28
30
|
invalid = false,
|
|
31
|
+
preference,
|
|
29
32
|
tone,
|
|
30
33
|
type = 'text',
|
|
31
34
|
...attrs
|
|
@@ -43,6 +46,9 @@ const resolvedTone = tone ?? dataTone;
|
|
|
43
46
|
data-tone={resolvedTone}
|
|
44
47
|
data-text-input-autofocus={autofocus === 'desktop' ? 'desktop' : undefined}
|
|
45
48
|
data-text-input-field
|
|
49
|
+
data-preference-id={preference?.id}
|
|
50
|
+
data-preference-path={preference?.path}
|
|
51
|
+
data-preference-control={preference ? 'text' : undefined}
|
|
46
52
|
>
|
|
47
53
|
<input
|
|
48
54
|
{...attrs}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
import type { Tone } from '../../../theme/contracts';
|
|
4
|
+
|
|
5
|
+
type Props = HTMLAttributes<'textarea'> & {
|
|
6
|
+
invalid?: boolean;
|
|
7
|
+
size?: 'default' | 'compact';
|
|
8
|
+
tone?: Tone;
|
|
9
|
+
value?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
'aria-invalid': ariaInvalid,
|
|
14
|
+
class: className,
|
|
15
|
+
'data-tone': dataTone,
|
|
16
|
+
invalid = false,
|
|
17
|
+
size = 'default',
|
|
18
|
+
tone,
|
|
19
|
+
value = '',
|
|
20
|
+
...attrs
|
|
21
|
+
}: Props = Astro.props;
|
|
22
|
+
const resolvedInvalid =
|
|
23
|
+
invalid || ariaInvalid === true || ariaInvalid === 'true';
|
|
24
|
+
const resolvedTone = tone ?? dataTone;
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<textarea
|
|
28
|
+
{...attrs}
|
|
29
|
+
class:list={['textarea', className]}
|
|
30
|
+
data-widget="textarea"
|
|
31
|
+
data-invalid={resolvedInvalid ? true : undefined}
|
|
32
|
+
data-size={size}
|
|
33
|
+
data-tone={resolvedTone}
|
|
34
|
+
aria-invalid={resolvedInvalid ? 'true' : ariaInvalid}
|
|
35
|
+
>{value}</textarea>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
.textarea {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
min-width: 0;
|
|
5
|
+
min-height: 28rem;
|
|
6
|
+
resize: vertical;
|
|
7
|
+
padding: var(--nox-field-control-padding-inline);
|
|
8
|
+
border: var(--nox-border-width) solid var(--nox-field-border);
|
|
9
|
+
border-radius: var(--nox-radius-sm);
|
|
10
|
+
outline: 0;
|
|
11
|
+
background: var(--nox-field-background);
|
|
12
|
+
color: var(--nox-field-color);
|
|
13
|
+
font-family: inherit;
|
|
14
|
+
font-size: var(--nox-field-control-font-size);
|
|
15
|
+
font-weight: var(--nox-font-weight-regular);
|
|
16
|
+
letter-spacing: 0;
|
|
17
|
+
line-height: 1.5;
|
|
18
|
+
transition:
|
|
19
|
+
border-color var(--nox-motion-duration-sm) var(--nox-motion-easing-standard),
|
|
20
|
+
box-shadow var(--nox-motion-duration-sm) var(--nox-motion-easing-standard);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.textarea::placeholder {
|
|
24
|
+
color: var(--nox-field-placeholder);
|
|
25
|
+
opacity: 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.textarea[data-size='compact'] {
|
|
29
|
+
min-height: calc(var(--nox-field-control-block-size) * 2);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.textarea:focus {
|
|
33
|
+
border-color: var(--nox-field-border-active);
|
|
34
|
+
box-shadow: var(--nox-field-focus-shadow);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.textarea[data-invalid] {
|
|
38
|
+
border-color: var(--nox-field-border-invalid);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.textarea:disabled {
|
|
42
|
+
background: var(--nox-field-background-disabled);
|
|
43
|
+
color: var(--nox-text-disabled);
|
|
44
|
+
cursor: not-allowed;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (hover: hover) and (pointer: fine) {
|
|
48
|
+
.textarea:not(:disabled):not(:focus):not([data-invalid]):hover {
|
|
49
|
+
border-color: var(--nox-field-border-hover);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@media (width < 48rem), (hover: none) and (pointer: coarse) {
|
|
54
|
+
.textarea {
|
|
55
|
+
min-height: 20rem;
|
|
56
|
+
font-size: var(--nox-font-size-md);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.textarea[data-size='compact'] {
|
|
60
|
+
min-height: calc(var(--nox-field-control-block-size) * 2);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
|
|
4
|
+
type Props = HTMLAttributes<'svg'>;
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
'aria-hidden': ariaHidden = 'true',
|
|
8
|
+
focusable = 'false',
|
|
9
|
+
...attrs
|
|
10
|
+
}: Props = Astro.props;
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<svg
|
|
14
|
+
{...attrs}
|
|
15
|
+
viewBox="0 0 32 32"
|
|
16
|
+
fill="none"
|
|
17
|
+
aria-hidden={ariaHidden}
|
|
18
|
+
focusable={focusable}
|
|
19
|
+
>
|
|
20
|
+
<path
|
|
21
|
+
d="M13 8 6 15l7 7M7 15h10c5 0 8 3 8 8"
|
|
22
|
+
stroke="currentColor"
|
|
23
|
+
stroke-linecap="round"
|
|
24
|
+
stroke-linejoin="round"
|
|
25
|
+
stroke-width="2.4"></path>
|
|
26
|
+
</svg>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
|
|
4
|
+
type Props = HTMLAttributes<'svg'>;
|
|
5
|
+
|
|
6
|
+
const attrs: Props = Astro.props;
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<svg
|
|
10
|
+
{...attrs}
|
|
11
|
+
viewBox="0 0 32 32"
|
|
12
|
+
fill="none"
|
|
13
|
+
aria-hidden="true"
|
|
14
|
+
focusable="false"
|
|
15
|
+
>
|
|
16
|
+
<path
|
|
17
|
+
d="M9 10H23M13 10V7H19V10M11 10L12 25H20L21 10M14.5 14V21M17.5 14V21"
|
|
18
|
+
stroke="currentColor"
|
|
19
|
+
stroke-width="2.5"
|
|
20
|
+
stroke-linecap="round"
|
|
21
|
+
stroke-linejoin="round"></path>
|
|
22
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
|
|
4
|
+
type Props = HTMLAttributes<'svg'>;
|
|
5
|
+
const attrs: Props = Astro.props;
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<svg
|
|
9
|
+
{...attrs}
|
|
10
|
+
viewBox="0 0 32 32"
|
|
11
|
+
fill="none"
|
|
12
|
+
aria-hidden="true"
|
|
13
|
+
focusable="false"
|
|
14
|
+
>
|
|
15
|
+
<circle cx="16" cy="16" r="8" fill="currentColor"></circle>
|
|
16
|
+
</svg>
|
package/src/components/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as ActionListItem } from './actions/ActionListItem/ActionListItem.astro';
|
|
2
2
|
export { default as Button } from './actions/Button/Button.astro';
|
|
3
3
|
export { default as CardAction } from './actions/CardAction/CardAction.astro';
|
|
4
|
+
export { default as IdentityProviderAction } from './actions/IdentityProviderAction/IdentityProviderAction.astro';
|
|
4
5
|
export { default as MediaTrigger } from './actions/MediaTrigger/MediaTrigger.astro';
|
|
5
6
|
export { default as ScrollToTop } from './actions/ScrollToTop/ScrollToTop.astro';
|
|
6
7
|
export { default as CardBody } from './content/CardBody/CardBody.astro';
|
|
@@ -16,11 +17,22 @@ export { default as MetricTile } from './data-display/MetricTile/MetricTile.astr
|
|
|
16
17
|
export { default as Tag } from './data-display/Tag/Tag.astro';
|
|
17
18
|
export { default as TextPair } from './data-display/TextPair/TextPair.astro';
|
|
18
19
|
export { default as Checkbox } from './forms/Checkbox/Checkbox.astro';
|
|
20
|
+
export { default as ChoiceGroup } from './forms/ChoiceGroup/ChoiceGroup.astro';
|
|
21
|
+
export type { ChoiceOption } from './forms/ChoiceGroup/contracts';
|
|
22
|
+
export { default as DateTimeInput } from './forms/DateTimeInput/DateTimeInput.astro';
|
|
19
23
|
export { default as FieldError } from './forms/FieldError/FieldError.astro';
|
|
20
24
|
export { default as FieldGroup } from './forms/FieldGroup/FieldGroup.astro';
|
|
21
25
|
export { default as FieldLabel } from './forms/FieldLabel/FieldLabel.astro';
|
|
26
|
+
export { default as PreparedFormBootstrap } from './forms/PreparedFormBootstrap/PreparedFormBootstrap.astro';
|
|
27
|
+
export type {
|
|
28
|
+
PreparedFormCombobox,
|
|
29
|
+
PreparedFormOption,
|
|
30
|
+
PreparedFormState,
|
|
31
|
+
} from './forms/PreparedFormBootstrap/contracts';
|
|
22
32
|
export { default as TextInput } from './forms/TextInput/TextInput.astro';
|
|
33
|
+
export { default as Textarea } from './forms/Textarea/Textarea.astro';
|
|
23
34
|
export { default as Spinner } from './feedback/Spinner/Spinner.astro';
|
|
35
|
+
export { default as PreferenceBootstrap } from './feedback/PreferenceBootstrap/PreferenceBootstrap.astro';
|
|
24
36
|
export { default as Tooltip } from './feedback/Tooltip/Tooltip.astro';
|
|
25
37
|
export { default as CanvasFrame } from './media/CanvasFrame/CanvasFrame.astro';
|
|
26
38
|
export { default as EmbedFrame } from './media/EmbedFrame/EmbedFrame.astro';
|
|
@@ -35,6 +47,7 @@ export { default as NavigationLink } from './navigation/NavigationLink.astro';
|
|
|
35
47
|
export { default as NavigationLinks } from './navigation/NavigationLinks.astro';
|
|
36
48
|
export { default as NavigationMenuList } from './navigation/NavigationMenuList.astro';
|
|
37
49
|
export { default as SkipLink } from './navigation/SkipLink/SkipLink.astro';
|
|
50
|
+
export { default as Footer } from './navigation/Footer/Footer.astro';
|
|
38
51
|
export { default as SubNavigation } from './navigation/SubNavigation/SubNavigation.astro';
|
|
39
52
|
export { default as SeoHead } from './seo/SeoHead.astro';
|
|
40
53
|
export * from './content/CodeBlock/contracts';
|
|
@@ -49,18 +62,22 @@ export * from './media/EmbedFrame/embedFrameController';
|
|
|
49
62
|
export * from './navigation/mobileNavigationController';
|
|
50
63
|
export * from './navigation/navigationState';
|
|
51
64
|
export * from './navigation/navigationTypes';
|
|
65
|
+
export * from './navigation/Footer/contracts';
|
|
52
66
|
export * from './widgetTypes';
|
|
53
67
|
export { default as ArrowDownIcon } from './icons/ArrowDownIcon.astro';
|
|
54
68
|
export { default as ArrowLeftIcon } from './icons/ArrowLeftIcon.astro';
|
|
55
69
|
export { default as ArrowRightIcon } from './icons/ArrowRightIcon.astro';
|
|
56
70
|
export { default as ArrowUpDownIcon } from './icons/ArrowUpDownIcon.astro';
|
|
57
71
|
export { default as ArrowUpIcon } from './icons/ArrowUpIcon.astro';
|
|
72
|
+
export { default as BackIcon } from './icons/BackIcon.astro';
|
|
58
73
|
export { default as BulletIcon } from './icons/BulletIcon.astro';
|
|
59
74
|
export { default as BurnIcon } from './icons/BurnIcon.astro';
|
|
75
|
+
export { default as CheckIcon } from './icons/CheckIcon.astro';
|
|
60
76
|
export { default as ClearIcon } from './icons/ClearIcon.astro';
|
|
61
77
|
export { default as CloseIcon } from './icons/CloseIcon.astro';
|
|
62
78
|
export { default as CopyIcon } from './icons/CopyIcon.astro';
|
|
63
79
|
export { default as DayIcon } from './icons/DayIcon.astro';
|
|
80
|
+
export { default as DeleteIcon } from './icons/DeleteIcon.astro';
|
|
64
81
|
export { default as DollarIcon } from './icons/DollarIcon.astro';
|
|
65
82
|
export { default as DownloadIcon } from './icons/DownloadIcon.astro';
|
|
66
83
|
export { default as EnterFullscreenIcon } from './icons/EnterFullscreenIcon.astro';
|
|
@@ -80,6 +97,7 @@ export { default as RibbonIcon } from './icons/RibbonIcon.astro';
|
|
|
80
97
|
export { default as SlashIcon } from './icons/SlashIcon.astro';
|
|
81
98
|
export { default as SlowIcon } from './icons/SlowIcon.astro';
|
|
82
99
|
export { default as StarIcon } from './icons/StarIcon.astro';
|
|
100
|
+
export { default as StatusIndicatorIcon } from './icons/StatusIndicatorIcon.astro';
|
|
83
101
|
export { default as StunIcon } from './icons/StunIcon.astro';
|
|
84
102
|
export { default as TableSortIcon } from './icons/TableSortIcon.astro';
|
|
85
103
|
export { default as WaterIcon } from './icons/WaterIcon.astro';
|
|
@@ -3,24 +3,18 @@ import type { HTMLAttributes } from 'astro/types';
|
|
|
3
3
|
import type { Tone } from '../../../theme/contracts';
|
|
4
4
|
import Button from '../../actions/Button/Button.astro';
|
|
5
5
|
import Spinner from '../../feedback/Spinner/Spinner.astro';
|
|
6
|
-
import FullscreenControl from '../../../patterns/Fullscreen/FullscreenControl.astro';
|
|
7
6
|
|
|
8
7
|
type CanvasAspectRatio = '16/9' | '4/3';
|
|
9
8
|
type CanvasActivation = 'immediate' | 'manual';
|
|
10
9
|
type CanvasWheelInput = 'canvas' | 'page';
|
|
11
10
|
|
|
12
|
-
type CanvasFullscreen = {
|
|
13
|
-
enterLabel: string;
|
|
14
|
-
exitLabel: string;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
11
|
type Props = HTMLAttributes<'div'> & {
|
|
18
12
|
activation?: CanvasActivation;
|
|
19
13
|
activationLabel?: string;
|
|
20
14
|
aspectRatio?: CanvasAspectRatio;
|
|
21
15
|
canvasId?: string;
|
|
22
16
|
frameId: string;
|
|
23
|
-
fullscreen?:
|
|
17
|
+
fullscreen?: boolean;
|
|
24
18
|
loadingLabel: string;
|
|
25
19
|
title: string;
|
|
26
20
|
tone?: Tone;
|
|
@@ -95,16 +89,6 @@ const resolvedCanvasId = canvasId ?? `${frameId}-canvas`;
|
|
|
95
89
|
role="alert"
|
|
96
90
|
hidden
|
|
97
91
|
></span>
|
|
98
|
-
{
|
|
99
|
-
fullscreen ? (
|
|
100
|
-
<FullscreenControl
|
|
101
|
-
targetId={frameId}
|
|
102
|
-
enterLabel={fullscreen.enterLabel}
|
|
103
|
-
exitLabel={fullscreen.exitLabel}
|
|
104
|
-
placement="overlay"
|
|
105
|
-
/>
|
|
106
|
-
) : null
|
|
107
|
-
}
|
|
108
92
|
</nox-canvas-frame>
|
|
109
93
|
|
|
110
94
|
<script>
|
|
@@ -3,19 +3,12 @@ import type { HTMLAttributes } from 'astro/types';
|
|
|
3
3
|
import type { Tone } from '../../../theme/contracts';
|
|
4
4
|
import Button from '../../actions/Button/Button.astro';
|
|
5
5
|
import Spinner from '../../feedback/Spinner/Spinner.astro';
|
|
6
|
-
import FullscreenControl from '../../../patterns/Fullscreen/FullscreenControl.astro';
|
|
7
6
|
|
|
8
7
|
type EmbedAspectRatio = '16/9' | '4/3';
|
|
9
8
|
type EmbedActivation = 'immediate' | 'manual';
|
|
10
9
|
type EmbedLoading = 'eager' | 'lazy';
|
|
11
10
|
type EmbedLoadingIndicator = 'none' | 'spinner';
|
|
12
11
|
|
|
13
|
-
type EmbedFullscreen = {
|
|
14
|
-
enterLabel: string;
|
|
15
|
-
exitLabel: string;
|
|
16
|
-
overlayOffset?: 'default' | 'native-controls';
|
|
17
|
-
};
|
|
18
|
-
|
|
19
12
|
type Props = Omit<
|
|
20
13
|
HTMLAttributes<'iframe'>,
|
|
21
14
|
'height' | 'loading' | 'src' | 'title' | 'width'
|
|
@@ -24,7 +17,7 @@ type Props = Omit<
|
|
|
24
17
|
activationLabel?: string;
|
|
25
18
|
aspectRatio?: EmbedAspectRatio;
|
|
26
19
|
frameId?: string;
|
|
27
|
-
fullscreen?:
|
|
20
|
+
fullscreen?: boolean;
|
|
28
21
|
loading?: EmbedLoading;
|
|
29
22
|
loadingIndicator?: EmbedLoadingIndicator;
|
|
30
23
|
loadingLabel: string;
|
|
@@ -111,17 +104,6 @@ const resolvedTone = tone ?? dataTone;
|
|
|
111
104
|
</span>
|
|
112
105
|
) : null
|
|
113
106
|
}
|
|
114
|
-
{
|
|
115
|
-
fullscreen ? (
|
|
116
|
-
<FullscreenControl
|
|
117
|
-
targetId={frameId ?? ''}
|
|
118
|
-
enterLabel={fullscreen.enterLabel}
|
|
119
|
-
exitLabel={fullscreen.exitLabel}
|
|
120
|
-
placement="overlay"
|
|
121
|
-
overlayOffset={fullscreen.overlayOffset}
|
|
122
|
-
/>
|
|
123
|
-
) : null
|
|
124
|
-
}
|
|
125
107
|
</nox-embed-frame>
|
|
126
108
|
|
|
127
109
|
<script>
|
|
@@ -3,6 +3,7 @@ import type { HTMLAttributes } from 'astro/types';
|
|
|
3
3
|
import type { BreadcrumbItem } from '../../../display/contracts';
|
|
4
4
|
import type { Tone } from '../../../theme/contracts';
|
|
5
5
|
import { defaultCoreMessages } from '../../../i18n/coreMessages';
|
|
6
|
+
import ArrowRightIcon from '../../icons/ArrowRightIcon.astro';
|
|
6
7
|
|
|
7
8
|
type Props = HTMLAttributes<'nav'> & {
|
|
8
9
|
items: readonly BreadcrumbItem[];
|
|
@@ -18,7 +19,7 @@ const {
|
|
|
18
19
|
tone,
|
|
19
20
|
...attrs
|
|
20
21
|
} = Astro.props;
|
|
21
|
-
const resolvedTone = tone ?? dataTone;
|
|
22
|
+
const resolvedTone = tone ?? dataTone ?? 'info';
|
|
22
23
|
---
|
|
23
24
|
|
|
24
25
|
{
|
|
@@ -38,6 +39,9 @@ const resolvedTone = tone ?? dataTone;
|
|
|
38
39
|
|
|
39
40
|
return (
|
|
40
41
|
<li class="breadcrumbs__item">
|
|
42
|
+
{index > 0 ? (
|
|
43
|
+
<ArrowRightIcon class="breadcrumbs__separator" />
|
|
44
|
+
) : null}
|
|
41
45
|
{isNavigable ? (
|
|
42
46
|
<a href={href} aria-current={isCurrent ? 'page' : undefined}>
|
|
43
47
|
{item.label}
|