@nordcode/ui 1.1.6 → 1.2.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.
Files changed (66) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/out/bundle.css +99 -16
  3. package/out/bundle_configless.css +99 -16
  4. package/out/complete.css +132 -22
  5. package/out/complete_configless.css +132 -22
  6. package/out/src/assets/fonts/DMMono-Regular.woff +0 -0
  7. package/out/src/assets/fonts/DMMono-Regular.woff2 +0 -0
  8. package/out/src/assets/fonts/fonts.css +7 -0
  9. package/out/src/assets/icons/ArrowRightSolid.svelte +1 -0
  10. package/out/src/assets/icons/arrow-right-solid.svg +1 -0
  11. package/out/src/assets/icons/favicon.png +0 -0
  12. package/out/src/assets/icons/favicon.svg +8 -0
  13. package/out/src/assets/logos/nordcode-logo-icon.svg +3 -0
  14. package/out/src/assets/logos/nordcode-logo.svg +17 -0
  15. package/out/src/modules/copyButtons/ts/copyButtons.ts +9 -0
  16. package/out/src/modules/dialogs/svelte/dialog.svelte +27 -0
  17. package/out/src/modules/dialogs/ts/LICENCE +171 -0
  18. package/out/src/modules/dialogs/ts/dialogs.ts +111 -0
  19. package/out/src/modules/notifications/js/notifications.js +294 -0
  20. package/out/src/modules/notifications/svelte/NotificationCenter.svelte +18 -0
  21. package/out/src/modules/notifications/svelte/NotificationTemplate.svelte +16 -0
  22. package/out/src/modules/sectionObserver/ts/sectionOberserver.ts +34 -0
  23. package/out/src/styles/bundle.css +7 -0
  24. package/out/src/styles/bundle_configless.css +5 -0
  25. package/out/src/styles/complete.css +5 -0
  26. package/out/src/styles/complete_configless.css +5 -0
  27. package/out/src/styles/components/alerts.css +20 -0
  28. package/out/src/styles/components/badges.css +14 -0
  29. package/out/src/styles/components/breadcrumbs.css +37 -0
  30. package/out/src/styles/components/bundle.css +13 -0
  31. package/out/src/styles/components/buttons.css +260 -0
  32. package/out/src/styles/components/card.css +55 -0
  33. package/out/src/styles/components/dialogs.css +138 -0
  34. package/out/src/styles/components/forms.css +41 -0
  35. package/out/src/styles/components/gallery.css +66 -0
  36. package/out/src/styles/components/icons.css +60 -0
  37. package/out/src/styles/components/inputs/base.css +249 -0
  38. package/out/src/styles/components/inputs/bundle.css +5 -0
  39. package/out/src/styles/components/inputs/fields.css +76 -0
  40. package/out/src/styles/components/inputs/segmented.css +114 -0
  41. package/out/src/styles/components/inputs/switch.css +42 -0
  42. package/out/src/styles/components/inputs/tag-select.css +41 -0
  43. package/out/src/styles/components/lists.css +40 -0
  44. package/out/src/styles/components/notifications.css +135 -0
  45. package/out/src/styles/components/tables.css +7 -0
  46. package/out/src/styles/config/bundle.css +2 -0
  47. package/out/src/styles/config/config.css +700 -0
  48. package/out/src/styles/config/extras.css +12 -0
  49. package/out/src/styles/exceptions/bundle.css +3 -0
  50. package/out/src/styles/exceptions/misc.css +21 -0
  51. package/out/src/styles/exceptions/spacings.css +15 -0
  52. package/out/src/styles/exceptions/typography.css +57 -0
  53. package/out/src/styles/theme/colors.css +165 -0
  54. package/out/src/styles/theme/colors_processed.css +87 -0
  55. package/out/src/styles/utils/base.css +415 -0
  56. package/out/src/styles/utils/bundle.css +6 -0
  57. package/out/src/styles/utils/easings.css +364 -0
  58. package/out/src/styles/utils/layouts.css +281 -0
  59. package/out/src/styles/utils/media.css +55 -0
  60. package/out/src/styles/utils/reset.css +145 -0
  61. package/out/src/styles/utils/theme.css +125 -0
  62. package/package.json +1 -1
  63. package/src/styles/components/card.css +29 -0
  64. package/src/styles/exceptions/typography.css +15 -0
  65. package/src/styles/utils/base.css +103 -9
  66. package/src/styles/utils/reset.css +4 -6
@@ -0,0 +1,294 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {T[keyof T]} valueOf<T>
5
+ * @template T
6
+ */
7
+
8
+ /**
9
+ * @typedef SelectorType
10
+ * @property {string} notificationTemplate
11
+ * @property {string} notification
12
+ * @property {string} notificationTitle
13
+ * @property {string} notificationDescription
14
+ * @property {string} notificationTime
15
+ * @property {string} notificationButton
16
+ * @property {string} notificationCenterToggle
17
+ * @property {string} notificationCenterDismissAll
18
+ * @property {string} notificationCenter
19
+ * @property {string} notificationCenterContainer
20
+ * @property {string} notificationOutput
21
+ */
22
+
23
+ /**
24
+ * @type {SelectorType}
25
+ */
26
+ export const Selector = {
27
+ notificationTemplate: '#nc-notification',
28
+ notification: '.nc-notification',
29
+ notificationTitle: '.nc-notification-title',
30
+ notificationDescription: '.nc-notification-description',
31
+ notificationTime: '.nc-notification-time',
32
+
33
+ notificationButton: 'button[data-has-notification]',
34
+ notificationCenterToggle: 'button[data-toggle-notification-center]',
35
+ notificationCenterDismissAll: 'button[data-notifications-dismiss-all]',
36
+
37
+ notificationCenter: '.nc-notification-center',
38
+ notificationCenterContainer: '.nc-notification-center-container',
39
+ notificationOutput: '.nc-notification-output',
40
+ };
41
+
42
+ /** @type {Set<string>} */
43
+ const notifications = new Set();
44
+
45
+ /** @type {function(): HTMLTemplateElement | null} */
46
+ const getNotificationTemplate = () => document.querySelector(Selector.notificationTemplate);
47
+
48
+ /** @type {function(): HTMLElement | null} */
49
+ const getNotificationCenter = () => document.querySelector(Selector.notificationCenter);
50
+
51
+ /** @type {function(): NodeListOf<HTMLButtonElement>} */
52
+ const getNotificationCenterToggle = () =>
53
+ document.querySelectorAll(Selector.notificationCenterToggle);
54
+
55
+ /** @type {function(): HTMLOutputElement | null} */
56
+ const getNotificationOutput = () => document.querySelector(Selector.notificationOutput);
57
+
58
+ /** @type {function(): NodeListOf<HTMLButtonElement>} */
59
+ const getNotificationCenterDismissAll = () =>
60
+ document.querySelectorAll(Selector.notificationCenterDismissAll);
61
+
62
+ /** @type {function(): HTMLElement | null} */
63
+ const getNotificationCenterContainer = () =>
64
+ document.querySelector(Selector.notificationCenterContainer);
65
+
66
+ /**
67
+ * Create a unique id for a notification
68
+ * @param {string} title
69
+ * @return {`${string}-${number}`}
70
+ */
71
+ const createNotificationId = (title) => {
72
+ return `${title}-${Date.now()}`;
73
+ };
74
+
75
+ /**
76
+ * Set the inner text of an element if it is defined
77
+ * @param {HTMLElement} notification
78
+ * @param {valueOf<SelectorType>} selector
79
+ * @param {string | undefined} text
80
+ */
81
+ const setElementTextIfItExists = (notification, selector, text) => {
82
+ /** @type {HTMLElement | null} */
83
+ const element = notification.querySelector(selector);
84
+
85
+ if (!element) {
86
+ return;
87
+ }
88
+
89
+ element.textContent = text || '';
90
+ };
91
+
92
+ /**
93
+ * Remove all notifications
94
+ */
95
+ const dismissAllNotifications = () => {
96
+ for (const notificationId of notifications) {
97
+ /** @type {HTMLElement | null} */
98
+ const notification = document.querySelector(`[data-notification-id="${notificationId}"]`);
99
+
100
+ if (!notification) {
101
+ return;
102
+ }
103
+
104
+ removeNotification(notificationId, notification);
105
+ }
106
+ };
107
+
108
+ /**
109
+ * Register all buttons
110
+ */
111
+ const setupNotificationButtons = () => {
112
+ const htmlEl = document.documentElement;
113
+
114
+ htmlEl?.addEventListener('click', (e) => {
115
+ const el = e.target;
116
+ if (el.hasAttribute('data-has-notification')) {
117
+ const title = el.dataset.notificationTitle;
118
+ const description = el.dataset.notificationDescription;
119
+
120
+ if (!title) {
121
+ console.error('No title defined for notification');
122
+ return;
123
+ }
124
+ addNotification(title, description);
125
+ }
126
+ });
127
+
128
+ for (const button of getNotificationCenterDismissAll()) {
129
+ button.addEventListener('click', () => {
130
+ dismissAllNotifications();
131
+ });
132
+ }
133
+
134
+ for (const button of getNotificationCenterToggle()) {
135
+ button.addEventListener('click', () => {
136
+ getNotificationCenter()?.classList.toggle('-open');
137
+ });
138
+ }
139
+ };
140
+
141
+ /**
142
+ * Hide the notification center
143
+ */
144
+ const closeNavigationCenter = () => {
145
+ getNotificationCenter()?.classList?.remove('-open');
146
+ };
147
+
148
+ /**
149
+ * Create a new notification from the template and set the necessary data and event listeners
150
+ * @param {string} title
151
+ * @param {string | undefined} description
152
+ * @param {string} notificationId
153
+ * @return {HTMLElement | null} The notification element
154
+ */
155
+ const createNotification = (title, description, notificationId) => {
156
+ const notificationTemplate = getNotificationTemplate();
157
+
158
+ if (!notificationTemplate) {
159
+ console.error('Could not find notification template', Selector.notificationTemplate);
160
+ return null;
161
+ }
162
+
163
+ const clonedTemplate = notificationTemplate.content.cloneNode(true);
164
+ /** @type {HTMLElement | null} */
165
+ const notificationElement = /** @type {HTMLTemplateElement} */ (clonedTemplate).querySelector(
166
+ Selector.notification,
167
+ );
168
+ if (!notificationElement) {
169
+ console.error('Could not find notification element');
170
+ return null;
171
+ }
172
+
173
+ /** @type {HTMLButtonElement | null} */
174
+ const notificationClose = notificationElement.querySelector('button');
175
+
176
+ notificationElement.dataset.notificationId = notificationId;
177
+ setElementTextIfItExists(notificationElement, Selector.notificationTitle, title);
178
+ setElementTextIfItExists(notificationElement, Selector.notificationDescription, description);
179
+ setElementTextIfItExists(
180
+ notificationElement,
181
+ Selector.notificationTime,
182
+ new Date().toLocaleTimeString(),
183
+ );
184
+
185
+ notificationClose?.addEventListener(
186
+ 'click',
187
+ (e) => {
188
+ closeCorrespondingNotification(e);
189
+ },
190
+ { once: true },
191
+ );
192
+
193
+ return notificationElement;
194
+ };
195
+
196
+ /**
197
+ * Handle the creation of the necessary DOM elements and add them to the DOM
198
+ * @param {string} title
199
+ * @param {string | undefined} description
200
+ */
201
+ export const addNotification = (title, description) => {
202
+ const notificationId = createNotificationId(title);
203
+ const liveNotification = createNotification(title, description, notificationId);
204
+ const notificationOutput = getNotificationOutput();
205
+
206
+ if (!liveNotification || !notificationOutput) {
207
+ return;
208
+ }
209
+
210
+ notificationOutput.append(liveNotification);
211
+ notifications.add(notificationId);
212
+
213
+ setTimeout(() => {
214
+ /** @type {HTMLElement | null} */
215
+ const notification = notificationOutput.querySelector(
216
+ `[data-notification-id="${notificationId}"]`,
217
+ );
218
+
219
+ if (!notification) {
220
+ return;
221
+ }
222
+
223
+ removeNotification(notificationId, notification, false);
224
+ const archiveNotification = createNotification(title, description, notificationId);
225
+ const notificationCenterContainer = getNotificationCenterContainer();
226
+ if (!archiveNotification || !notificationCenterContainer) {
227
+ return;
228
+ }
229
+ notificationCenterContainer.append(archiveNotification);
230
+ }, 4000);
231
+ };
232
+
233
+ /**
234
+ * Close the notification that is associated with the button that was clicked
235
+ * @param {MouseEvent} e
236
+ */
237
+ const closeCorrespondingNotification = (e) => {
238
+ /** @type {HTMLElement | null} */
239
+ const notification = /** @type {HTMLButtonElement} */ (e.target).closest(Selector.notification);
240
+
241
+ const notificationId = notification?.dataset?.notificationId;
242
+ if (!notificationId) {
243
+ return;
244
+ }
245
+ removeAllNotificationsWithId(notificationId);
246
+ };
247
+
248
+ /**
249
+ * Remove a notification from the DOM after playing the closing animation
250
+ *
251
+ * @param {string} notificationId
252
+ * @param {HTMLElement | null} notification
253
+ * @param {boolean} removeId
254
+ */
255
+ const removeNotification = (notificationId, notification, removeId = true) => {
256
+ if (!notification) {
257
+ return;
258
+ }
259
+
260
+ notification.addEventListener(
261
+ 'animationend',
262
+ () => {
263
+ notification.remove();
264
+
265
+ if (removeId) {
266
+ notifications.delete(notificationId);
267
+ }
268
+
269
+ if (notifications.size === 0) {
270
+ closeNavigationCenter();
271
+ }
272
+ },
273
+ { once: true },
274
+ );
275
+
276
+ notification.classList.add('-closing');
277
+ };
278
+
279
+ /**
280
+ * Remove all notifications with the same id. This is used to remove the live notification and the archived notification
281
+ * @param {string} notificationId
282
+ */
283
+ const removeAllNotificationsWithId = (notificationId) => {
284
+ /** @type {NodeListOf<HTMLElement>} */
285
+ const relatedNotifications = document.querySelectorAll(
286
+ `[data-notification-id="${notificationId}"]`,
287
+ );
288
+
289
+ for (const n of relatedNotifications) {
290
+ removeNotification(notificationId, n);
291
+ }
292
+ };
293
+
294
+ setupNotificationButtons();
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ interface NotificationCenterProps {
3
+ dismissAllText: string;
4
+ closeText: string;
5
+ }
6
+
7
+ let { dismissAllText = 'Dismiss all', closeText = 'Close' }: NotificationCenterProps = $props();
8
+ </script>
9
+
10
+ <div class="nc-notification-center -archive">
11
+ <div class="nc-notification-center-header">
12
+ <button data-notifications-dismiss-all class="nc-button">{dismissAllText}</button>
13
+ <button data-toggle-notification-center class="nc-button">{closeText}</button>
14
+ </div>
15
+ <div class="nc-notification-center-container"></div>
16
+ </div>
17
+
18
+ <output class="nc-notification-output"></output>
@@ -0,0 +1,16 @@
1
+ <script>
2
+
3
+ </script>
4
+
5
+
6
+ <template id="nc-notification">
7
+ <div class="nc-notification">
8
+ <p class="nc-notification-title"></p>
9
+ <p class="nc-notification-description">Some notification</p>
10
+ <div class="nc-notification-footer">
11
+ <button class="nc-button -small">Dismiss</button>
12
+
13
+ <time class="nc-notification-time"></time>
14
+ </div>
15
+ </div>
16
+ </template>
@@ -0,0 +1,34 @@
1
+ const buildThresholds = (steps: number) => {
2
+ const thresholds = [0];
3
+ for (let i = 1.0; i <= steps; i++) {
4
+ const ratio = i / steps;
5
+ thresholds.push(ratio);
6
+ }
7
+ return thresholds;
8
+ };
9
+
10
+ const createObserver = (selector: string, steps: number) => {
11
+ // if the browser does not support the IntersectionObserver API, return
12
+ if (!('IntersectionObserver' in window)) {
13
+ return;
14
+ }
15
+
16
+ const options = {
17
+ root: null,
18
+ rootMargin: '0px',
19
+ threshold: buildThresholds(steps),
20
+ };
21
+
22
+ const observer = new IntersectionObserver((entries) => {
23
+ for (const entry of entries) {
24
+ const ratio = entry.intersectionRatio;
25
+ (entry.target as HTMLElement)?.style?.setProperty('--intersecting', ratio.toString());
26
+ }
27
+ }, options);
28
+
29
+ for (const node of Array.from(document.querySelectorAll(selector))) {
30
+ observer.observe(node);
31
+ }
32
+ };
33
+
34
+ export { createObserver };
@@ -0,0 +1,7 @@
1
+ @layer config, theme, reset, base, utils, components, helpers;
2
+
3
+ @import "./config/bundle.css";
4
+ @import "./theme/colors.css";
5
+
6
+ @import "./utils/bundle.css";
7
+ @import "./exceptions/bundle.css";
@@ -0,0 +1,5 @@
1
+ @layer config, theme, reset, base, utils, components, helpers;
2
+
3
+ @import "./theme/colors.css";
4
+ @import "./utils/bundle.css";
5
+ @import "./exceptions/bundle.css";
@@ -0,0 +1,5 @@
1
+ @layer config, theme, reset, base, utils, components, helpers;
2
+
3
+ @import "./bundle.css";
4
+
5
+ @import "./components/bundle.css";
@@ -0,0 +1,5 @@
1
+ @layer config, theme, reset, base, utils, components, helpers;
2
+
3
+ @import "./bundle_configless.css";
4
+
5
+ @import "./components/bundle.css";
@@ -0,0 +1,20 @@
1
+ @layer components.alerts {
2
+ :where(.nc-alert) {
3
+ background: var(--surface);
4
+ color: var(--text);
5
+ gap: 1ch;
6
+ }
7
+
8
+ :where(.nc-alert)>.nc-icon {
9
+ margin-block: calc((var(--line-height-base) - var(--icon-size)) / 2);
10
+ }
11
+
12
+ :where(.nc-alert-title) {
13
+ font-weight: var(--font-weight-heading);
14
+ }
15
+
16
+ :where(.nc-alert.-filled) {
17
+ background: var(--surface-hover);
18
+ color: var(--text-hover);
19
+ }
20
+ }
@@ -0,0 +1,14 @@
1
+ @layer components.badge {
2
+ :where(.badge) {
3
+ font-family: var(--font-family-mono);
4
+ letter-spacing: var(--tracking-tight);
5
+ font-weight: var(--font-weight-default);
6
+ color: var(--text, var(--color-text-base));
7
+ border: var(--border-width-thin) solid var(--text, var(--color-text-base));
8
+ border-radius: var(--border-radius-small);
9
+ background: var(--surface, transparent);
10
+ padding: 0.5lh 1ch;
11
+ inline-size: max-content;
12
+ line-height: 1;
13
+ }
14
+ }
@@ -0,0 +1,37 @@
1
+ @layer components.breadcrumbs {
2
+ :where(.nc-breadcrumbs) {
3
+ inline-size: max-content;
4
+ max-inline-size: 100%;
5
+ background-color: var(--nc-breadcrumbs-surface, transparent);
6
+ color: var(--nc-breadcrumbs-text, --color-text-muted);
7
+ }
8
+
9
+ :where(.nc-breadcrumb-item) {
10
+ color: inherit;
11
+
12
+ &:last-child {
13
+ color: var(--color-brand-primary-base);
14
+ }
15
+
16
+ &:not(:last-child):after {
17
+ padding-inline: 1ch;
18
+ color: inherit;
19
+ content: "›";
20
+ font-size: inherit;
21
+ }
22
+ }
23
+
24
+ :where(.nc-breadcrumb-link) {
25
+ text-decoration: none;
26
+ color: inherit;
27
+
28
+ &:hover {
29
+ text-decoration: underline;
30
+ }
31
+
32
+ &[aria-current="page"] {
33
+ pointer-events: none;
34
+ color: var(--nc-breadcrumbs-text-active, --color-text-base);
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,13 @@
1
+ @import "./alerts.css";
2
+ @import "./badges.css";
3
+ @import "./breadcrumbs.css";
4
+ @import "./buttons.css";
5
+ @import "./card.css";
6
+ @import "./dialogs.css";
7
+ @import "./forms.css";
8
+ @import "./gallery.css";
9
+ @import "./icons.css";
10
+ @import "./inputs/bundle.css";
11
+ @import "./lists.css";
12
+ @import "./notifications.css";
13
+ @import "./tables.css";