@functionalcms/svelte-components 3.0.6 → 3.0.7

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 (53) hide show
  1. package/dist/components/Banner.svelte +5 -3
  2. package/dist/components/Link.svelte +54 -44
  3. package/dist/components/Logo.svelte +15 -3
  4. package/dist/components/Spacer.svelte +10 -7
  5. package/dist/components/Well.svelte +15 -12
  6. package/dist/components/agnostic/Alert/Alert.svelte +64 -57
  7. package/dist/components/agnostic/Avatar/Avatar.svelte +19 -15
  8. package/dist/components/agnostic/Breadcrumb/Breadcrumb.svelte +19 -10
  9. package/dist/components/agnostic/Button/Button.svelte +60 -35
  10. package/dist/components/agnostic/Button/ButtonGroup.svelte +4 -3
  11. package/dist/components/agnostic/Card/Card.svelte +22 -18
  12. package/dist/components/agnostic/ChoiceInput/ChoiceInput.svelte +87 -59
  13. package/dist/components/agnostic/Close/Close.svelte +11 -7
  14. package/dist/components/agnostic/Dialog/Dialog.svelte +64 -42
  15. package/dist/components/agnostic/Dialog/SvelteA11yDialog.svelte +76 -51
  16. package/dist/components/agnostic/Disclose/Disclose.svelte +15 -9
  17. package/dist/components/agnostic/Divider/Divider.svelte +21 -11
  18. package/dist/components/agnostic/Drawer/Drawer.svelte +20 -16
  19. package/dist/components/agnostic/EmptyState/EmptyState.svelte +10 -7
  20. package/dist/components/agnostic/Header/Header.svelte +22 -15
  21. package/dist/components/agnostic/Header/HeaderNav.svelte +4 -3
  22. package/dist/components/agnostic/Header/HeaderNavItem.svelte +3 -2
  23. package/dist/components/agnostic/Icon/Icon.svelte +28 -20
  24. package/dist/components/agnostic/Loader/Loader.svelte +6 -3
  25. package/dist/components/agnostic/Progress/Progress.svelte +5 -4
  26. package/dist/components/agnostic/Spinner/Spinner.svelte +6 -3
  27. package/dist/components/agnostic/Table/Table.svelte +191 -134
  28. package/dist/components/agnostic/Tabs/TabButtonCustom.svelte +24 -12
  29. package/dist/components/agnostic/Tabs/Tabs.svelte +173 -104
  30. package/dist/components/agnostic/Tag/Tag.svelte +14 -10
  31. package/dist/components/agnostic/Tag/TagSlots.svelte +2 -1
  32. package/dist/components/agnostic/Toasts/Toasts.svelte +29 -19
  33. package/dist/components/agnostic/Tooltip/Tooltip.svelte +85 -68
  34. package/dist/components/agnostic/Tooltip/TooltipSlots.svelte +2 -1
  35. package/dist/components/blog/BlogDescription.svelte +6 -4
  36. package/dist/components/blog/BlogTitle.svelte +8 -6
  37. package/dist/components/form/Input.svelte +81 -52
  38. package/dist/components/form/Input.svelte.d.ts +2 -2
  39. package/dist/components/form/Select.svelte +40 -24
  40. package/dist/components/layouts/DefaultLayout.svelte +8 -5
  41. package/dist/components/layouts/Meta.svelte +7 -6
  42. package/dist/components/layouts/SimpleFooter.svelte +13 -3
  43. package/dist/components/layouts/Tracker.svelte +2 -1
  44. package/dist/components/layouts/TwoColumnsLayout.svelte +3 -2
  45. package/dist/components/menu/CollapsibleMenu.svelte +18 -13
  46. package/dist/components/menu/DynamicMenu.svelte +16 -10
  47. package/dist/components/menu/HamburgerMenu.svelte +24 -18
  48. package/dist/components/menu/Menu.svelte +279 -219
  49. package/dist/components/menu/MenuItem.svelte +14 -10
  50. package/dist/components/menu/NavigationItems.svelte +18 -12
  51. package/dist/components/presentation/Carusel.svelte +77 -72
  52. package/dist/components/presentation/Gallery.svelte +14 -8
  53. package/package.json +9 -10
@@ -171,110 +171,179 @@ if we'd like to only blank out buttons but otherwise skin ourselves. */
171
171
 
172
172
  </style>
173
173
 
174
- <script>export let size = "";
175
- export let tabs = [];
176
- export let isBorderless = false;
177
- export let isVerticalOrientation = false;
178
- export let isDisabled = false;
179
- export let disabledOptions = [];
180
- export let isSkinned = true;
181
- let dynamicComponentRefs = [];
182
- let tabButtonRefs = [];
183
- $: dynamicComponentRefs = [];
184
- $: tabButtonRefs = [];
185
- const baseStyles = () => `tabs ${isVerticalOrientation ? "tabs-vertical" : ""}`;
186
- const selectTab = (index) => {
187
- tabs = tabs.map((tab, i) => {
188
- tab.isActive = index === i ? true : false;
189
- return tab;
190
- });
191
- };
192
- let activeTabs = tabs.filter((tab) => tab.isActive);
193
- if (activeTabs.length === 0) {
194
- selectTab(0);
195
- }
196
- $: tablistClasses = () => {
197
- const tabListClass = isSkinned ? "tab-list" : "tab-list-base";
198
- return [tabListClass, isBorderless ? `tab-borderless` : ""].filter((klass) => klass.length).join(" ");
199
- };
200
- $: tabButtonClasses = (tab) => {
201
- const klasses = [
202
- `tab-item`,
203
- `tab-button`,
204
- tab.isActive ? "active" : "",
205
- size === "large" ? "tab-button-large" : "",
206
- size === "xlarge" ? "tab-button-xlarge" : ""
207
- ];
208
- return klasses.filter((klass) => klass.length).join(" ");
209
- };
210
- const focusTab = (index, direction) => {
211
- let i = index;
212
- if (direction === "asc") {
213
- i += 1;
214
- } else if (direction === "desc") {
215
- i -= 1;
216
- }
217
- if (i < 0) {
218
- i = tabs.length - 1;
219
- } else if (i >= tabs.length) {
220
- i = 0;
221
- }
222
- let nextTab;
223
- if (tabButtonRefs.length) {
224
- nextTab = tabButtonRefs[i];
225
- } else if (dynamicComponentRefs.length) {
226
- nextTab = dynamicComponentRefs[i];
227
- }
228
- if (nextTab.isDisabled && nextTab.isDisabled() || nextTab.disabled && direction) {
229
- focusTab(i, direction);
230
- } else {
231
- nextTab.focus();
232
- }
233
- };
234
- const handleKeyDown = (ev, index) => {
235
- switch (ev.key) {
236
- case "Up":
237
- case "ArrowUp":
238
- if (isVerticalOrientation) {
239
- focusTab(index, "desc");
240
- }
241
- break;
242
- case "Down":
243
- case "ArrowDown":
244
- if (isVerticalOrientation) {
245
- focusTab(index, "asc");
246
- }
247
- break;
248
- case "Left":
249
- case "ArrowLeft":
250
- if (!isVerticalOrientation) {
251
- focusTab(index, "desc");
252
- }
253
- break;
254
- case "Right":
255
- case "ArrowRight":
256
- if (!isVerticalOrientation) {
257
- focusTab(index, "asc");
258
- }
259
- break;
260
- case "Home":
261
- case "ArrowHome":
262
- focusTab(0);
263
- break;
264
- case "End":
265
- case "ArrowEnd":
266
- focusTab(tabs.length - 1);
267
- break;
268
- case "Enter":
269
- case "Space":
270
- focusTab(index);
271
- selectTab(index);
272
- break;
273
- default:
274
- return;
275
- }
276
- ev.preventDefault();
277
- };
174
+ <script lang="ts">
175
+ import type { NavigationDirection, Tab, TabSizes } from './api';
176
+
177
+ export let size: TabSizes = '';
178
+
179
+ /**
180
+ * This is an array of objects in shape like:
181
+ * {
182
+ title: "Tab 3",
183
+ tabPanelComponent: MyTabPanel,
184
+ // This is optional and only if you want to supply your own custom tab buttons.
185
+ // If not passed, we will generate an internal default tab button.
186
+ tabButtonComponent: TabButton3,
187
+ },
188
+ */
189
+ export let tabs: Tab[] = [];
190
+
191
+ export let isBorderless = false;
192
+ export let isVerticalOrientation = false;
193
+ export let isDisabled = false;
194
+ export let disabledOptions: string[] = [];
195
+ export let isSkinned = true;
196
+
197
+ /**
198
+ * Explanation: we have two ways that the tab buttons get created:
199
+ * 1. The `tabs` input array has dynamic `tabButtonComponent` components.
200
+ * 2. The `tabs` has no `tabButtonComponent` and so we generate the tab
201
+ * button internally.
202
+ *
203
+ * As such, the `dynamicComponentRefs` below are refs for case 1. and
204
+ * `tabButtonRefs` are refs for case 2.
205
+ */
206
+ let dynamicComponentRefs = []; // https://svelte.dev/tutorial/component-this
207
+ let tabButtonRefs = [];
208
+
209
+ // handle element removal by filtering null
210
+ $: dynamicComponentRefs = [];
211
+ // dynamicComponentRefs.filter(el => el);
212
+ // $: console.log(dynamicComponentRefs);
213
+ $: tabButtonRefs = [];
214
+ // tabButtonRefs.filter(el => el);
215
+ // $: console.log(tabButtonRefs);
216
+
217
+ // onMount(() => {
218
+ // console.log(tabButtonRefs);
219
+ // });
220
+ const baseStyles = () =>
221
+ `tabs ${isVerticalOrientation ? 'tabs-vertical' : ''}`;
222
+
223
+ const selectTab = (index: number) => {
224
+ tabs = tabs.map((tab, i) => {
225
+ tab.isActive = index === i ? true : false;
226
+ return tab;
227
+ });
228
+ };
229
+ let activeTabs = tabs.filter((tab: Tab) => tab.isActive);
230
+ if (activeTabs.length === 0) {
231
+ selectTab(0);
232
+ }
233
+
234
+ $: tablistClasses = () => {
235
+ const tabListClass = isSkinned ? 'tab-list' : 'tab-list-base';
236
+ return [tabListClass, isBorderless ? `tab-borderless` : '']
237
+ .filter((klass) => klass.length)
238
+ .join(' ');
239
+ };
240
+
241
+ $: tabButtonClasses = (tab: Tab) => {
242
+ const klasses = [
243
+ `tab-item`,
244
+ `tab-button`,
245
+ tab.isActive ? 'active' : '',
246
+ size === 'large' ? 'tab-button-large' : '',
247
+ size === 'xlarge' ? 'tab-button-xlarge' : ''
248
+ ];
249
+ return klasses.filter((klass) => klass.length).join(' ');
250
+ };
251
+
252
+ const focusTab = (index: number, direction?: NavigationDirection) => {
253
+ // console.log("tabButtonRefs: ", tabButtonRefs);
254
+ // console.log("dynamicComponentRefs: ", dynamicComponentRefs);
255
+ /**
256
+ * direction is optional because we only need that when we're arrow navigating.
257
+ * If they've hit ENTER|SPACE we're focusing the current item. If HOME focus(0).
258
+ * If END focus(tabButtons.length - 1)...and so on.
259
+ */
260
+ let i = index;
261
+ if (direction === 'asc') {
262
+ i += 1;
263
+ } else if (direction === 'desc') {
264
+ i -= 1;
265
+ }
266
+
267
+ // Circular navigation
268
+ //
269
+ // If we've went beyond "start" circle around to last
270
+ if (i < 0) {
271
+ i = tabs.length - 1;
272
+ } else if (i >= tabs.length) {
273
+ // We've went beyond "last" so circle around to first
274
+ i = 0;
275
+ }
276
+
277
+ /**
278
+ * Figure out at run-time whether this was build with dynamicComponentRefs (consumer
279
+ * used their own tabButtonComponent), or tabButtonRefs (we generated the buttons here)
280
+ */
281
+
282
+ let nextTab;
283
+ if (tabButtonRefs.length) {
284
+ nextTab = tabButtonRefs[i];
285
+ } else if (dynamicComponentRefs.length) {
286
+ // Same logic as above, but we're using the binding to component instance
287
+ nextTab = dynamicComponentRefs[i];
288
+ }
289
+ // Edge case: We hit a tab button that's been disabled. If so, we recurse, but
290
+ // only if we've been supplied a `direction`. Otherwise, nothing left to do.
291
+ if (
292
+ (nextTab.isDisabled && nextTab.isDisabled()) ||
293
+ (nextTab.disabled && direction)
294
+ ) {
295
+ // Retry with new `i` index going in same direction
296
+ focusTab(i, direction);
297
+ } else {
298
+ // Nominal case is to just focs next tab :)
299
+ nextTab.focus();
300
+ }
301
+ };
302
+
303
+ const handleKeyDown = (ev: KeyboardEvent, index: number) => {
304
+ switch (ev.key) {
305
+ case 'Up': // These first cases are IEEdge :(
306
+ case 'ArrowUp':
307
+ if (isVerticalOrientation) {
308
+ focusTab(index, 'desc');
309
+ }
310
+ break;
311
+ case 'Down':
312
+ case 'ArrowDown':
313
+ if (isVerticalOrientation) {
314
+ focusTab(index, 'asc');
315
+ }
316
+ break;
317
+ case 'Left':
318
+ case 'ArrowLeft':
319
+ if (!isVerticalOrientation) {
320
+ focusTab(index, 'desc');
321
+ }
322
+ break;
323
+ case 'Right':
324
+ case 'ArrowRight':
325
+ if (!isVerticalOrientation) {
326
+ focusTab(index, 'asc');
327
+ }
328
+ break;
329
+ case 'Home':
330
+ case 'ArrowHome':
331
+ focusTab(0);
332
+ break;
333
+ case 'End':
334
+ case 'ArrowEnd':
335
+ focusTab(tabs.length - 1);
336
+ break;
337
+ case 'Enter':
338
+ case 'Space':
339
+ focusTab(index);
340
+ selectTab(index);
341
+ break;
342
+ default:
343
+ return;
344
+ }
345
+ ev.preventDefault();
346
+ };
278
347
  </script>
279
348
 
280
349
  <div class="{baseStyles()}">
@@ -57,16 +57,20 @@
57
57
 
58
58
  </style>
59
59
 
60
- <script>export let isUppercase = false;
61
- export let isSkinned = true;
62
- export let type = "";
63
- export let shape = "";
64
- const tagClasses = [
65
- isSkinned ? "tag" : "tag-base",
66
- type ? `tag-${type}` : "",
67
- shape ? `tag-${shape}` : "",
68
- isUppercase ? "tag-upper" : ""
69
- ].filter((c) => c).join(" ");
60
+ <script lang="ts">
61
+ export let isUppercase = false;
62
+ export let isSkinned = true;
63
+ export let type = "";
64
+ export let shape = "";
65
+
66
+ const tagClasses = [
67
+ isSkinned ? "tag" : "tag-base",
68
+ type ? `tag-${type}` : "",
69
+ shape ? `tag-${shape}` : "",
70
+ isUppercase ? "tag-upper" : "",
71
+ ]
72
+ .filter((c) => c)
73
+ .join(" ");
70
74
  </script>
71
75
 
72
76
  <span class={tagClasses}>
@@ -4,7 +4,8 @@
4
4
  }
5
5
  </style>
6
6
 
7
- <script>import Tag from "./Tag.svelte";
7
+ <script lang="ts">
8
+ import Tag from "./Tag.svelte";
8
9
  </script>
9
10
 
10
11
  <div>
@@ -18,25 +18,35 @@
18
18
 
19
19
  </style>
20
20
 
21
- <script>import { onMount } from "svelte";
22
- export let portalRootSelector = "body";
23
- export let horizontalPosition;
24
- export let verticalPosition;
25
- const portalTarget = portalRootSelector || "body";
26
- $: toastClasses = [
27
- "alert-toast",
28
- horizontalPosition,
29
- verticalPosition
30
- ].filter((c) => c.length).join(" ");
31
- let mounted = false;
32
- onMount(() => mounted = true);
33
- const teleportNode = async (node) => {
34
- const destination = document.querySelector(portalTarget);
35
- destination.appendChild(node);
36
- };
37
- const teleport = (node) => {
38
- teleportNode(node);
39
- };
21
+ <script lang="ts">
22
+ import { onMount } from "svelte";
23
+ export let portalRootSelector = "body";
24
+ export let horizontalPosition: "start" | "center" | "end";
25
+ export let verticalPosition: "top" | "bottom";
26
+ const portalTarget = portalRootSelector || "body";
27
+
28
+ $: toastClasses = [
29
+ "alert-toast",
30
+ horizontalPosition,
31
+ verticalPosition
32
+ ].filter(c => c.length).join(" ");
33
+
34
+ // In case of SSR we don't render element until hydration is complete
35
+ let mounted = false;
36
+ onMount(() => (mounted = true));
37
+
38
+ const teleportNode = async (node) => {
39
+ const destination = document.querySelector(portalTarget);
40
+ destination.appendChild(node);
41
+ };
42
+
43
+ /**
44
+ * Svelte actions don't want to be async so this is a hack
45
+ * to get around that by delegating to teleportNode
46
+ */
47
+ const teleport = (node) => {
48
+ teleportNode(node);
49
+ };
40
50
  </script>
41
51
 
42
52
  {#if mounted}
@@ -18,74 +18,91 @@
18
18
  }
19
19
 
20
20
  </style>
21
- <script>import {
22
- computePosition,
23
- flip,
24
- offset as fuOffset,
25
- shift,
26
- arrow
27
- } from "@floating-ui/dom";
28
- export let placement = "top";
29
- export let offset = 6;
30
- let tooltipRef;
31
- let tooltipTargetRef;
32
- let tooltipArrowRef;
33
- const uid = () => `tip-${Date.now().toString(32)}-${Math.random().toString(16).replace(/\./g, "").toString()}`;
34
- const id = uid();
35
- const update = () => {
36
- const tip = tooltipRef;
37
- const target = tooltipTargetRef;
38
- const arrowEl = tooltipArrowRef;
39
- if (tip && target && arrowEl) {
40
- computePosition(target, tip, {
41
- placement,
42
- middleware: [
43
- fuOffset(offset),
44
- flip(),
45
- shift({ padding: 4 }),
46
- arrow({
47
- element: arrowEl,
48
- // Offset from edge; fixes issue on left-start, left-end, right-start,
49
- // etc., where arrow oddly overlaps the rounded corner of content box
50
- padding: 10
51
- })
52
- ]
53
- }).then(({ x, y, placement: placement2, middlewareData }) => {
54
- const arrowX = middlewareData.arrow.x;
55
- const arrowY = middlewareData.arrow.y;
56
- const staticSide = {
57
- top: "bottom",
58
- right: "left",
59
- bottom: "top",
60
- left: "right"
61
- }[placement2.split("-")[0]];
62
- Object.assign(tip.style, {
63
- left: `${x}px`,
64
- top: `${y}px`
65
- });
66
- Object.assign(arrowEl.style, {
67
- left: typeof arrowX === "number" ? `${arrowX}px` : "",
68
- top: typeof arrowY === "number" ? `${arrowY}px` : "",
69
- right: "",
70
- bottom: "",
71
- [staticSide]: "-4px"
72
- });
73
- });
74
- }
75
- };
76
- const showTooltip = () => {
77
- if (tooltipRef) {
78
- tooltipRef.style.display = "block";
79
- }
80
- update();
81
- };
82
- const hideTooltip = () => {
83
- if (tooltipRef) {
84
- tooltipRef.style.display = "";
85
- }
86
- };
87
- const tooltipClasses = "tooltip";
88
- const tooltipArrowClasses = "tooltip-arrow";
21
+ <script lang="ts">
22
+ import {
23
+ computePosition,
24
+ flip,
25
+ offset as fuOffset,
26
+ shift,
27
+ arrow,
28
+ } from "@floating-ui/dom";
29
+ import type { TooltipPlacement } from './api';
30
+
31
+ export let placement: TooltipPlacement = "top";
32
+ export let offset: number = 6;
33
+
34
+ let tooltipRef;
35
+ let tooltipTargetRef;
36
+ let tooltipArrowRef;
37
+
38
+ const uid = () =>
39
+ `tip-${Date.now().toString(32)}-${Math.random()
40
+ .toString(16)
41
+ .replace(/\./g, "")
42
+ .toString()}`;
43
+
44
+ const id = uid();
45
+
46
+
47
+ const update = () => {
48
+ const tip = tooltipRef;
49
+ const target = tooltipTargetRef;
50
+ const arrowEl = tooltipArrowRef;
51
+
52
+ if (tip && target && arrowEl) {
53
+ computePosition(target, tip, {
54
+ placement: placement,
55
+ middleware: [
56
+ fuOffset(offset),
57
+ flip(),
58
+ shift({ padding: 4 }),
59
+ arrow({
60
+ element: arrowEl,
61
+ // Offset from edge; fixes issue on left-start, left-end, right-start,
62
+ // etc., where arrow oddly overlaps the rounded corner of content box
63
+ padding: 10,
64
+ }),
65
+ ],
66
+ }).then(({ x, y, placement, middlewareData }) => {
67
+ const arrowX = middlewareData.arrow!.x;
68
+ const arrowY = middlewareData.arrow!.y;
69
+ const staticSide = {
70
+ top: "bottom",
71
+ right: "left",
72
+ bottom: "top",
73
+ left: "right",
74
+ }[placement.split("-")[0]]!;
75
+
76
+ Object.assign(tip.style, {
77
+ left: `${x}px`,
78
+ top: `${y}px`,
79
+ });
80
+
81
+ Object.assign(arrowEl.style, {
82
+ left: typeof arrowX === "number" ? `${arrowX}px` : "",
83
+ top: typeof arrowY === "number" ? `${arrowY}px` : "",
84
+ right: "",
85
+ bottom: "",
86
+ [staticSide]: "-4px",
87
+ });
88
+ });
89
+ }
90
+ }
91
+
92
+ const showTooltip = () => {
93
+ if (tooltipRef) {
94
+ tooltipRef.style.display = "block";
95
+ }
96
+ update();
97
+ };
98
+
99
+ const hideTooltip = () => {
100
+ if (tooltipRef) {
101
+ tooltipRef.style.display = "";
102
+ }
103
+ };
104
+ const tooltipClasses = "tooltip";
105
+ const tooltipArrowClasses = "tooltip-arrow";
89
106
  </script>
90
107
  <div
91
108
  bind:this={tooltipTargetRef}
@@ -16,7 +16,8 @@
16
16
  }
17
17
  </style>
18
18
 
19
- <script>import Tooltip from "./Tooltip.svelte";
19
+ <script lang="ts">
20
+ import Tooltip from "./Tooltip.svelte";
20
21
  </script>
21
22
 
22
23
  <div class="h4 mbs40">Tooltips</div>
@@ -1,7 +1,9 @@
1
- <script>import Link from "../Link.svelte";
2
- import { Justify } from "../Styling.js";
3
- export let description;
4
- export let css = "";
1
+ <script lang="ts">
2
+ import Link from "../Link.svelte";
3
+ import { Justify } from "../Styling.js";
4
+
5
+ export let description: string;
6
+ export let css: string = "";
5
7
  </script>
6
8
 
7
9
  <div class={css}>
@@ -1,9 +1,11 @@
1
- <script>export let slug = "";
2
- export let path = "";
3
- export let title;
4
- export let css = "";
5
- const href = `${path}/${slug}`;
6
- const isLink = slug != "";
1
+ <script lang="ts">
2
+ export let slug = '';
3
+ export let path: string = '';
4
+ export let title: string;
5
+ export let css: string = "";
6
+
7
+ const href = `${path}/${slug}`;
8
+ const isLink = slug != '';
7
9
  </script>
8
10
 
9
11
  <h1 class={css}>