@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.
Files changed (88) hide show
  1. package/package.json +7 -1
  2. package/src/admin/cache.ts +217 -0
  3. package/src/admin/contracts.ts +28 -0
  4. package/src/admin/index.ts +3 -0
  5. package/src/admin/module.ts +28 -0
  6. package/src/auth/contracts.ts +53 -0
  7. package/src/auth/firebase/client.ts +83 -0
  8. package/src/auth/firebase/contracts.ts +8 -0
  9. package/src/auth/firebase/index.ts +1 -0
  10. package/src/auth/index.ts +2 -0
  11. package/src/auth/module.ts +99 -0
  12. package/src/client/formSubmission.ts +177 -0
  13. package/src/client/index.ts +4 -0
  14. package/src/client/preferences.ts +400 -0
  15. package/src/components/actions/Button/Button.astro +42 -6
  16. package/src/components/actions/Button/Button.css +19 -0
  17. package/src/components/actions/IdentityProviderAction/IdentityProviderAction.astro +35 -0
  18. package/src/components/actions/ScrollToTop/ScrollToTop.css +11 -0
  19. package/src/components/content/CardBody/CardBody.astro +3 -0
  20. package/src/components/content/CardBody/CardBody.css +16 -2
  21. package/src/components/content/CardFooter/CardFooter.astro +9 -0
  22. package/src/components/content/CardFooter/CardFooter.css +45 -3
  23. package/src/components/content/CardLink/CardLink.astro +12 -3
  24. package/src/components/content/CardLink/CardLink.css +32 -0
  25. package/src/components/content/MarkdownContent/MarkdownContent.css +14 -4
  26. package/src/components/content/MarkdownContent/MarkdownInline.astro +1 -1
  27. package/src/components/content/MarkdownContent/contracts.ts +1 -1
  28. package/src/components/content/MarkdownContent/markdownContentRenderer.ts +552 -0
  29. package/src/components/data-display/TextPair/TextPair.css +8 -2
  30. package/src/components/feedback/PreferenceBootstrap/PreferenceBootstrap.astro +403 -0
  31. package/src/components/forms/Checkbox/Checkbox.astro +6 -0
  32. package/src/components/forms/ChoiceGroup/ChoiceGroup.astro +57 -0
  33. package/src/components/forms/ChoiceGroup/ChoiceGroup.css +108 -0
  34. package/src/components/forms/ChoiceGroup/contracts.ts +9 -0
  35. package/src/components/forms/DateTimeInput/DateTimeInput.astro +14 -0
  36. package/src/components/forms/PreparedFormBootstrap/PreparedFormBootstrap.astro +203 -0
  37. package/src/components/forms/PreparedFormBootstrap/contracts.ts +15 -0
  38. package/src/components/forms/TextInput/TextInput.astro +7 -1
  39. package/src/components/forms/Textarea/Textarea.astro +35 -0
  40. package/src/components/forms/Textarea/Textarea.css +62 -0
  41. package/src/components/icons/BackIcon.astro +26 -0
  42. package/src/components/icons/DeleteIcon.astro +22 -0
  43. package/src/components/icons/StatusIndicatorIcon.astro +16 -0
  44. package/src/components/index.ts +18 -0
  45. package/src/components/media/CanvasFrame/CanvasFrame.astro +1 -17
  46. package/src/components/media/EmbedFrame/EmbedFrame.astro +1 -19
  47. package/src/components/media/EmbedFrame/EmbedFrame.css +0 -2
  48. package/src/components/navigation/Breadcrumbs/Breadcrumbs.astro +5 -1
  49. package/src/components/navigation/Breadcrumbs/Breadcrumbs.css +12 -17
  50. package/src/components/navigation/Footer/Footer.astro +102 -0
  51. package/src/components/navigation/Footer/Footer.css +155 -0
  52. package/src/components/navigation/Footer/contracts.ts +17 -0
  53. package/src/components/navigation/SubNavigation/SubNavigation.css +0 -5
  54. package/src/composition/Grid/Grid.css +16 -0
  55. package/src/composition/SurfaceGroup/SurfaceGroup.css +21 -7
  56. package/src/composition/SurfaceGroup/stickySurfaceGroupController.ts +3 -0
  57. package/src/data/firestore/client/contracts.ts +78 -0
  58. package/src/data/firestore/client/firebase.ts +56 -0
  59. package/src/data/firestore/client/index.ts +3 -0
  60. package/src/data/firestore/client/repository.ts +111 -0
  61. package/src/display/contracts.ts +44 -1
  62. package/src/display/index.ts +1 -0
  63. package/src/display/tableProgressive.ts +62 -0
  64. package/src/layouts/BaseLayout.astro +8 -1
  65. package/src/patterns/Combobox/Combobox.astro +23 -0
  66. package/src/patterns/Combobox/comboboxController.ts +69 -0
  67. package/src/patterns/Fullscreen/FullscreenControl.astro +4 -14
  68. package/src/patterns/Fullscreen/FullscreenControl.css +0 -26
  69. package/src/patterns/Modal/Modal.astro +1 -1
  70. package/src/patterns/Modal/Modal.css +38 -1
  71. package/src/patterns/Table/Table.astro +122 -7
  72. package/src/patterns/Table/TableBody.astro +8 -0
  73. package/src/patterns/Table/TableBody.css +3 -3
  74. package/src/patterns/Table/TableCell.css +11 -1
  75. package/src/patterns/Table/TableCellValue.astro +31 -0
  76. package/src/patterns/Table/TableFooter.astro +3 -1
  77. package/src/patterns/Table/TableHeader.astro +1 -0
  78. package/src/patterns/Table/TablePagination.astro +63 -47
  79. package/src/patterns/Table/TableSkeleton.astro +18 -22
  80. package/src/patterns/Table/TableSkeleton.css +30 -5
  81. package/src/patterns/Table/tableClientController.ts +253 -0
  82. package/src/patterns/Table/tableFilterController.ts +23 -31
  83. package/src/patterns/Table/tableProgressiveController.ts +615 -227
  84. package/src/patterns/Table/tableSortController.ts +25 -7
  85. package/src/styles/base.css +24 -7
  86. package/src/styles/interaction.css +16 -0
  87. package/src/styles/style.css +3 -0
  88. package/src/styles/tokens.css +5 -0
@@ -0,0 +1,35 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types';
3
+ import type { Tone } from '../../../theme/contracts';
4
+ import Button from '../Button/Button.astro';
5
+
6
+ type Props = HTMLAttributes<'button'> & {
7
+ label: string;
8
+ pendingLabel?: string;
9
+ tone?: Tone;
10
+ };
11
+
12
+ const {
13
+ label,
14
+ pendingLabel = label,
15
+ tone,
16
+ ...attrs
17
+ }: Props = Astro.props;
18
+ ---
19
+
20
+ <Button
21
+ {...attrs}
22
+ type="button"
23
+ prominent
24
+ tone={tone}
25
+ data-auth-provider-action
26
+ data-auth-provider-label={label}
27
+ data-auth-provider-pending-label={pendingLabel}
28
+ >
29
+ {
30
+ Astro.slots.has('leading') ? (
31
+ <span slot="leading"><slot name="leading" /></span>
32
+ ) : null
33
+ }
34
+ <span data-auth-provider-action-label>{label}</span>
35
+ </Button>
@@ -11,9 +11,20 @@
11
11
  block-size: var(--nox-section-compact-block-size);
12
12
  min-block-size: 0;
13
13
  box-shadow: var(--nox-shadow-surface);
14
+ opacity: 0.8;
15
+ }
16
+
17
+ .scroll-to-top.nox-button:is(:focus-visible, :active) {
18
+ opacity: 1;
14
19
  }
15
20
 
16
21
  html:has(dialog[open]) .scroll-to-top,
17
22
  html:has(:fullscreen) .scroll-to-top {
18
23
  display: none;
19
24
  }
25
+
26
+ @media (hover: hover) and (pointer: fine) {
27
+ .scroll-to-top.nox-button:hover {
28
+ opacity: 1;
29
+ }
30
+ }
@@ -5,6 +5,7 @@ type Props = HTMLAttributes<'div'> & {
5
5
  id?: string;
6
6
  inset?: 'default' | 'none';
7
7
  overlayBoundary?: boolean;
8
+ scrollable?: boolean;
8
9
  };
9
10
 
10
11
  const {
@@ -12,6 +13,7 @@ const {
12
13
  id,
13
14
  inset = 'default',
14
15
  overlayBoundary = false,
16
+ scrollable = false,
15
17
  ...attrs
16
18
  }: Props = Astro.props;
17
19
  ---
@@ -24,6 +26,7 @@ const {
24
26
  data-surface
25
27
  data-inset={inset}
26
28
  data-overlay-boundary={overlayBoundary ? true : undefined}
29
+ data-scrollable={scrollable ? true : undefined}
27
30
  >
28
31
  <div class="card-body__content">
29
32
  <slot />
@@ -41,13 +41,22 @@
41
41
  overflow: clip;
42
42
  }
43
43
 
44
+ .card-body[data-scrollable] {
45
+ overflow: auto;
46
+ overscroll-behavior: contain;
47
+ }
48
+
49
+ .card-body[data-scrollable] .card-body__content {
50
+ min-block-size: 100%;
51
+ align-self: flex-start;
52
+ }
53
+
44
54
  .card-body p {
45
55
  margin: 0;
46
56
  }
47
57
 
48
58
  .card-body a {
49
- color: var(--nox-link);
50
- text-underline-offset: 0.2em;
59
+ color: var(--nox-content-link-color);
51
60
  }
52
61
 
53
62
  .card-body strong {
@@ -55,6 +64,11 @@
55
64
  font-weight: var(--nox-font-weight-strong);
56
65
  }
57
66
 
67
+ .card-body a strong {
68
+ color: inherit;
69
+ font-weight: var(--nox-content-link-emphasis-font-weight);
70
+ }
71
+
58
72
  @container (width < 32rem) {
59
73
  .card-body__content {
60
74
  --nox-content-padding: var(--nox-space-4);
@@ -18,6 +18,7 @@ const {
18
18
  }: Props = Astro.props;
19
19
  const resolvedTone = tone ?? dataTone;
20
20
  const hasAction = Astro.slots.has('action');
21
+ const hasLeadingAction = Astro.slots.has('leading-action');
21
22
  const hasMedia = Boolean(media);
22
23
  ---
23
24
 
@@ -28,10 +29,18 @@ const hasMedia = Boolean(media);
28
29
  data-surface
29
30
  data-surface-sizing="content"
30
31
  data-has-action={hasAction ? true : undefined}
32
+ data-has-leading-action={hasLeadingAction ? true : undefined}
31
33
  data-has-media={hasMedia ? true : undefined}
32
34
  data-tone={resolvedTone}
33
35
  >
34
36
  <div class="card-footer__layout">
37
+ {
38
+ hasLeadingAction ? (
39
+ <div class="card-footer__leading-action">
40
+ <slot name="leading-action" />
41
+ </div>
42
+ ) : null
43
+ }
35
44
  {
36
45
  media ? (
37
46
  <div class="card-footer__media" aria-hidden="true">
@@ -31,6 +31,10 @@
31
31
  grid-template-columns: minmax(0, 1fr) var(--card-footer-size);
32
32
  }
33
33
 
34
+ .card-footer[data-has-leading-action] .card-footer__layout {
35
+ grid-template-columns: var(--card-footer-size) minmax(0, 1fr);
36
+ }
37
+
34
38
  .card-footer[data-has-media][data-has-action] .card-footer__layout {
35
39
  grid-template-columns:
36
40
  var(--card-footer-size)
@@ -38,6 +42,31 @@
38
42
  var(--card-footer-size);
39
43
  }
40
44
 
45
+ .card-footer[data-has-leading-action][data-has-action]
46
+ .card-footer__layout {
47
+ grid-template-columns:
48
+ var(--card-footer-size)
49
+ minmax(0, 1fr)
50
+ var(--card-footer-size);
51
+ }
52
+
53
+ .card-footer[data-has-leading-action][data-has-media]
54
+ .card-footer__layout {
55
+ grid-template-columns:
56
+ var(--card-footer-size)
57
+ var(--card-footer-size)
58
+ minmax(0, 1fr);
59
+ }
60
+
61
+ .card-footer[data-has-leading-action][data-has-media][data-has-action]
62
+ .card-footer__layout {
63
+ grid-template-columns:
64
+ var(--card-footer-size)
65
+ var(--card-footer-size)
66
+ minmax(0, 1fr)
67
+ var(--card-footer-size);
68
+ }
69
+
41
70
  .card-footer__media {
42
71
  display: grid;
43
72
  min-width: 0;
@@ -64,29 +93,42 @@
64
93
  align-items: center;
65
94
  padding: var(--nox-space-3) var(--nox-space-5);
66
95
  font-size: var(--nox-font-size-sm);
67
- font-weight: var(--nox-font-weight-medium);
96
+ font-weight: var(--nox-font-weight-regular);
68
97
  line-height: var(--nox-line-height-tight);
69
98
  overflow-wrap: anywhere;
70
99
  }
71
100
 
72
101
  .card-footer__content a {
73
- color: var(--nox-link);
74
- text-underline-offset: 0.2em;
102
+ color: var(--nox-content-link-color);
103
+ font-weight: var(--nox-content-link-emphasis-font-weight);
75
104
  }
76
105
 
77
106
  .card-footer__content strong {
78
107
  font-weight: var(--nox-font-weight-strong);
79
108
  }
80
109
 
110
+ .card-footer__content a strong {
111
+ font-weight: var(--nox-content-link-emphasis-font-weight);
112
+ }
113
+
114
+ .card-footer__leading-action,
81
115
  .card-footer__action {
82
116
  display: grid;
83
117
  min-width: 0;
84
118
  min-height: var(--card-footer-size);
85
119
  place-items: stretch;
86
120
  overflow: hidden;
121
+ }
122
+
123
+ .card-footer__leading-action {
124
+ border-inline-end: var(--nox-border-width) solid var(--surface-border-color);
125
+ }
126
+
127
+ .card-footer__action {
87
128
  border-inline-start: var(--nox-border-width) solid var(--surface-border-color);
88
129
  }
89
130
 
131
+ .card-footer__leading-action > .nox-button[data-button-borderless],
90
132
  .card-footer__action > .nox-button[data-button-borderless] {
91
133
  --nox-button-background: transparent;
92
134
  }
@@ -20,6 +20,7 @@ const {
20
20
  compactContent,
21
21
  compactText,
22
22
  compactVisual = 'show',
23
+ density = 'default',
23
24
  disabled = false,
24
25
  direction,
25
26
  full = false,
@@ -32,11 +33,15 @@ const {
32
33
  mediaSize = 'default',
33
34
  meta,
34
35
  mode = 'link',
36
+ textLayout = 'inline',
37
+ textTreatment = 'default',
35
38
  tone,
36
39
  title,
37
40
  ...attrs
38
41
  }: Props = Astro.props;
39
- const accessibleLabel = `${label} : ${title}${meta !== undefined ? ` ${meta}` : ''}`;
42
+ const accessibleLabel = [label, title, meta]
43
+ .filter((value) => value !== undefined && value !== '')
44
+ .join(' ');
40
45
  const isDisabled = disabled || (mode === 'link' && !href);
41
46
  const isInteractive = mode === 'link' && !isDisabled;
42
47
  const Root = isInteractive ? 'a' : 'span';
@@ -65,6 +70,7 @@ const resolvedTone = tone ?? dataTone;
65
70
  data-collapse={collapse}
66
71
  data-compact-content={resolvedCompactContent}
67
72
  data-compact-visual={compactVisual}
73
+ data-density={density}
68
74
  data-disabled={isDisabled ? 'true' : 'false'}
69
75
  data-direction={direction}
70
76
  data-full={full ? 'true' : 'false'}
@@ -74,6 +80,7 @@ const resolvedTone = tone ?? dataTone;
74
80
  data-media-position={hasVisual ? mediaPosition : undefined}
75
81
  data-media-size={hasVisual ? mediaSize : undefined}
76
82
  data-mode={mode}
83
+ data-text-treatment={textTreatment}
77
84
  data-tone={resolvedTone}
78
85
  >
79
86
  <span class="card-link__layout">
@@ -109,12 +116,14 @@ const resolvedTone = tone ?? dataTone;
109
116
  <span class="card-link__compact-text" aria-hidden="true">
110
117
  {compactText}
111
118
  </span>
112
- <span class="card-link__label">{label}</span>
119
+ {label ? <span class="card-link__label">{label}</span> : null}
113
120
  <TextPair
114
121
  class="card-link__text"
115
- layout="inline"
122
+ layout={textLayout}
116
123
  primary={title}
124
+ primaryWeight={isInteractive ? 'medium' : 'strong'}
117
125
  secondary={meta}
126
+ secondaryWeight={textTreatment === 'heading' ? 'regular' : 'medium'}
118
127
  />
119
128
  </span>
120
129
  </span>
@@ -202,6 +202,20 @@
202
202
  gap: var(--nox-space-1);
203
203
  }
204
204
 
205
+ .card-link[data-density='relaxed'] .card-link__layout {
206
+ --card-link-size: calc(
207
+ var(--nox-navigation-block-size) + var(--nox-space-5)
208
+ );
209
+ }
210
+
211
+ .card-link[data-density='relaxed'] .card-link__content {
212
+ padding: var(--nox-space-5) var(--nox-space-6);
213
+ }
214
+
215
+ .card-link[data-density='relaxed'] .card-link__text {
216
+ gap: var(--nox-space-3);
217
+ }
218
+
205
219
  .card-link__compact-text {
206
220
  display: none;
207
221
  min-width: 0;
@@ -233,6 +247,14 @@
233
247
  align-items: center;
234
248
  }
235
249
 
250
+ .card-link[data-text-treatment='heading'] .card-link__text {
251
+ --text-pair-primary-font-size: var(--nox-font-size-lg);
252
+ --text-pair-primary-letter-spacing: var(--nox-letter-spacing-wide);
253
+ --text-pair-primary-text-transform: uppercase;
254
+ --text-pair-secondary-font-size: var(--nox-font-size-md);
255
+ line-height: var(--nox-line-height-tight);
256
+ }
257
+
236
258
  .card-link[data-interactive='true']:active {
237
259
  background: var(--card-link-active-background);
238
260
  }
@@ -287,6 +309,16 @@
287
309
  }
288
310
 
289
311
  @media (width < 48rem) {
312
+ .card-link[data-density='relaxed'] .card-link__layout {
313
+ --card-link-size: calc(
314
+ var(--nox-navigation-block-size) + var(--nox-space-4)
315
+ );
316
+ }
317
+
318
+ .card-link[data-density='relaxed'] .card-link__content {
319
+ padding: var(--nox-space-4) var(--nox-space-5);
320
+ }
321
+
290
322
  .card-link[data-compact-content] .card-link__layout {
291
323
  --card-link-size: var(--nox-navigation-compact-block-size);
292
324
  --card-link-media-size: 2.125rem;
@@ -171,7 +171,7 @@
171
171
 
172
172
  .markdown-content__resource-title {
173
173
  font-size: var(--nox-font-size-md);
174
- font-weight: var(--nox-font-weight-strong);
174
+ font-weight: var(--nox-font-weight-regular);
175
175
  line-height: var(--nox-line-height-tight);
176
176
  }
177
177
 
@@ -298,13 +298,23 @@
298
298
  }
299
299
 
300
300
  .markdown-content__link {
301
- color: var(--nox-tone-color);
301
+ color: var(--nox-content-link-color);
302
302
  overflow-wrap: anywhere;
303
303
  text-decoration: none;
304
304
  }
305
305
 
306
- .markdown-content__link[data-markdown-link-treatment='reference'] {
307
- font-weight: var(--nox-font-weight-strong);
306
+ .markdown-content__link[data-markdown-link-treatment='primary'] {
307
+ font-weight: var(--nox-content-link-emphasis-font-weight);
308
+ }
309
+
310
+ .markdown-content .markdown-content__strong {
311
+ font-weight: var(--nox-font-weight-medium);
312
+ }
313
+
314
+ @media (hover: hover) and (pointer: fine) {
315
+ .markdown-content__link:hover {
316
+ text-decoration-line: underline;
317
+ }
308
318
  }
309
319
 
310
320
  .markdown-content [data-tone] {
@@ -19,7 +19,7 @@ const { node }: Props = Astro.props;
19
19
  ) : node.type === 'symbol' ? (
20
20
  <MarkdownSymbol node={node} />
21
21
  ) : node.type === 'strong' ? (
22
- <strong>
22
+ <strong class="markdown-content__strong">
23
23
  {node.children.map((child) => <Astro.self node={child} />)}
24
24
  </strong>
25
25
  ) : node.type === 'emphasis' ? (
@@ -49,7 +49,7 @@ export type MarkdownLink = {
49
49
  external: boolean;
50
50
  href: string;
51
51
  lang?: string;
52
- treatment?: 'reference';
52
+ treatment?: 'primary';
53
53
  };
54
54
 
55
55
  export type MarkdownBreak = {