@onsvisual/svelte-components 0.0.1

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 (46) hide show
  1. package/README.md +5 -0
  2. package/dist/@types/actions/cssVariables/index.d.ts +4 -0
  3. package/dist/@types/actions/resizeObserver/index.d.ts +4 -0
  4. package/dist/@types/components/layout/Accordion/Accordion.svelte.d.ts +27 -0
  5. package/dist/@types/components/layout/Accordion/AccordionItem.svelte.d.ts +31 -0
  6. package/dist/@types/components/layout/Container/Container.svelte.d.ts +39 -0
  7. package/dist/@types/components/layout/Footer/Footer.svelte.d.ts +31 -0
  8. package/dist/@types/components/layout/Footer/ONSLogo.svelte.d.ts +29 -0
  9. package/dist/@types/components/layout/Header/Header.svelte.d.ts +35 -0
  10. package/dist/@types/components/layout/Header/ONSLogo.svelte.d.ts +29 -0
  11. package/dist/@types/components/layout/Theme/Theme.svelte.d.ts +33 -0
  12. package/dist/@types/components/layout/Theme/themes.d.ts +29 -0
  13. package/dist/@types/components/layout/Twisty/Twisty.svelte.d.ts +29 -0
  14. package/dist/@types/components/ui/Button/Button.svelte.d.ts +43 -0
  15. package/dist/@types/components/ui/Button/Icon.svelte.d.ts +27 -0
  16. package/dist/@types/components/ui/Dropdown/Dropdown.svelte.d.ts +37 -0
  17. package/dist/@types/components/ui/Em/Em.svelte.d.ts +29 -0
  18. package/dist/@types/components/ui/Input/Input.svelte.d.ts +51 -0
  19. package/dist/@types/components/ui/Select/Select.svelte.d.ts +67 -0
  20. package/dist/@types/components/ui/Textarea/Textarea.svelte.d.ts +37 -0
  21. package/dist/@types/index.d.ts +13 -0
  22. package/dist/@types/js/utils.d.ts +10 -0
  23. package/dist/actions/cssVariables/index.js +20 -0
  24. package/dist/actions/resizeObserver/index.js +25 -0
  25. package/dist/components/layout/Accordion/Accordion.svelte +37 -0
  26. package/dist/components/layout/Accordion/AccordionItem.svelte +81 -0
  27. package/dist/components/layout/Container/Container.svelte +99 -0
  28. package/dist/components/layout/Footer/Footer.svelte +266 -0
  29. package/dist/components/layout/Footer/ONSLogo.svelte +150 -0
  30. package/dist/components/layout/Header/Header.svelte +513 -0
  31. package/dist/components/layout/Header/ONSLogo.svelte +150 -0
  32. package/dist/components/layout/Theme/Theme.svelte +91 -0
  33. package/dist/components/layout/Theme/themes.js +24 -0
  34. package/dist/components/layout/Twisty/Twisty.svelte +48 -0
  35. package/dist/components/ui/Button/Button.svelte +87 -0
  36. package/dist/components/ui/Button/Icon.svelte +50 -0
  37. package/dist/components/ui/Dropdown/Dropdown.svelte +62 -0
  38. package/dist/components/ui/Em/Em.svelte +44 -0
  39. package/dist/components/ui/Input/Input.svelte +163 -0
  40. package/dist/components/ui/Select/Select.svelte +257 -0
  41. package/dist/components/ui/Textarea/Textarea.svelte +99 -0
  42. package/dist/css/main.css +55 -0
  43. package/dist/globals.d.ts +23 -0
  44. package/dist/index.js +16 -0
  45. package/dist/js/utils.js +41 -0
  46. package/package.json +144 -0
@@ -0,0 +1,163 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+ const dispatch = createEventDispatcher();
5
+
6
+ /**
7
+ * ID for &lt;input&gt; element
8
+ * @type {string}
9
+ */
10
+ export let id = "";
11
+ /**
12
+ * A prop to bind to for the entered value
13
+ * @type {string}
14
+ */
15
+ export let value = "";
16
+ /**
17
+ * A label to describe the &lt;input&gt; element (expected for accessibility)
18
+ * @type {string}
19
+ */
20
+ export let label = "Enter some text";
21
+ /**
22
+ * Visually hide the label
23
+ * @type {boolean}
24
+ */
25
+ export let hideLabel = false;
26
+ /**
27
+ * An optional description to help users know what to enter
28
+ * @type {string}
29
+ */
30
+ export let description = "";
31
+ /**
32
+ * The maximum number of characters that can be entered (optional)
33
+ * @type {number}
34
+ */
35
+ export let charLimit = null;
36
+ /**
37
+ * The width of the &lt;input&gt; in characters
38
+ * @type {number}
39
+ */
40
+ export let width = null;
41
+ /**
42
+ * An optional prefix (eg. £) to appear on the left of the input
43
+ * @type {string}
44
+ */
45
+ export let prefix = "";
46
+ /**
47
+ * An optional suffix (eg. %) to appear on the right of the input
48
+ * @type {string}
49
+ */
50
+ export let suffix = "";
51
+ /**
52
+ * An optional hidden description of the prefix (for accessibility)
53
+ * @type {string}
54
+ */
55
+ export let unitLabel = prefix || suffix || "";
56
+ /**
57
+ * An optional regex pattern foto limit the input (not currently used)
58
+ * @type {string}
59
+ */
60
+ export let pattern = "";
61
+ /**
62
+ * Set to `true` if the value should be a number
63
+ * @type {boolean}
64
+ */
65
+ export let numeric = false;
66
+ /**
67
+ * Set to `true` to highlight border in red
68
+ * @type {boolean}
69
+ */
70
+ export let error = false;
71
+ </script>
72
+
73
+ <div class="ons-field">
74
+ {#if label}
75
+ <label
76
+ class="ons-label"
77
+ class:ons-label--with-description="{description}"
78
+ class:ons-u-vh="{hideLabel}"
79
+ aria-describedby="{description ? `${id}-description-hint` : null}"
80
+ for="{id}"
81
+ >
82
+ {label}
83
+ </label>
84
+ {/if}
85
+ {#if description}
86
+ <span id="{id}-description-hint" class="ons-label__description ons-input--with-description">
87
+ {description}
88
+ </span>
89
+ {/if}
90
+ {#if prefix || suffix}
91
+ <span class="ons-input-type" class:ons-input-type--prefix="{prefix}">
92
+ <span class="ons-input-type__inner">
93
+ <input
94
+ type="text"
95
+ id="{id}"
96
+ bind:value="{value}"
97
+ maxlength="{charLimit}"
98
+ pattern="{pattern ? pattern : numeric ? '[0-9]*' : null}"
99
+ inputmode="{numeric ? 'numeric' : null}"
100
+ class="ons-input ons-input--text ons-input-type__input {Number.isInteger(width)
101
+ ? `ons-input--w-${width}`
102
+ : ''}"
103
+ class:ons-input--error="{error}"
104
+ aria-labelledby="{id} {id}-unit"
105
+ aria-describedby="{description ? `${id}-description-hint` : null}"
106
+ on:change="{(e) => dispatch('change', e)}"
107
+ />
108
+ <abbr
109
+ id="{id}-unit"
110
+ class="ons-input-type__type ons-js-input-abbr"
111
+ aria-label="{unitLabel}"
112
+ role="figure"
113
+ title="{unitLabel}">{prefix || suffix}</abbr
114
+ >
115
+ </span>
116
+ </span>
117
+ {:else}
118
+ <input
119
+ type="text"
120
+ id="{id}"
121
+ bind:value="{value}"
122
+ pattern="{pattern ? pattern : numeric ? '[0-9]*' : null}"
123
+ inputmode="{numeric ? 'numeric' : null}"
124
+ class="ons-input ons-input--text ons-input-type__input {Number.isInteger(width)
125
+ ? `ons-input--w-${width}`
126
+ : ''}"
127
+ class:ons-input--error="{error}"
128
+ aria-describedby="{description ? `${id}-description-hint` : null}"
129
+ on:change="{(e) => dispatch('change', e)}"
130
+ />
131
+ {/if}
132
+ </div>
133
+
134
+ <style>
135
+ .ons-input {
136
+ background: none;
137
+ border-color: currentColor;
138
+ }
139
+ .ons-input--error {
140
+ background: none;
141
+ border-color: rgb(208, 2, 27);
142
+ }
143
+ .ons-input--error:focus {
144
+ border-color: currentColor;
145
+ }
146
+ .ons-js-input-abbr {
147
+ background: var(--hinted, #e2e2e3);
148
+ border-color: currentColor;
149
+ }
150
+ .ons-input-type--prefix .ons-input--error {
151
+ border-left-color: currentColor;
152
+ border-right-color: rgb(208, 2, 27);
153
+ }
154
+ .ons-input--error + .ons-js-input-abbr {
155
+ color: #e2e2e3;
156
+ border-color: #222;
157
+ }
158
+ .ons-input-type__input:focus + .ons-input-type__type::after {
159
+ box-shadow: 0 0 0 1px currentColor, 0 0 0 4px #fbc900;
160
+ }
161
+ .ons-input-type__input.ons-input--error:focus + .ons-input-type__type::after {
162
+ box-shadow: 0 0 0 1px #222, 0 0 0 4px #fbc900;
163
+ }</style>
@@ -0,0 +1,257 @@
1
+ <script>
2
+ import SelectInner from "svelte-select";
3
+
4
+ /**
5
+ * Unique id for the element
6
+ * @type {string}
7
+ */
8
+ export let id = "";
9
+ /**
10
+ * The mode can be either "default" or "search"
11
+ * @type {"default"|"search"}
12
+ */
13
+ export let mode = "default";
14
+ /**
15
+ * Enable multi-select mode
16
+ * @type {boolean}
17
+ */
18
+ export let multiple = false;
19
+ /**
20
+ * Set a limit on the number of items in multi-select mode
21
+ * @type {number}
22
+ */
23
+ export let maxSelected = 4;
24
+ /**
25
+ * Defines whether the selection can be cleared
26
+ * @type {boolean}
27
+ */
28
+ export let clearable = true;
29
+ /**
30
+ * A label to describe the element (expected for accessibility)
31
+ * @type {string}
32
+ */
33
+ export let label = "";
34
+ /**
35
+ * Visually hide the label
36
+ * @type {boolean}
37
+ */
38
+ export let hideLabel = false;
39
+ /**
40
+ * An optional placeholder text
41
+ * @type {string}
42
+ */
43
+ export let placeholder = "Select an option";
44
+ /**
45
+ * A prop to bind to for the selected value (will be an array for multi-select)
46
+ * @type {object}
47
+ */
48
+ export let value = null;
49
+ /**
50
+ * An array of options, formatted {id, label}
51
+ * @type {array}
52
+ */
53
+ export let options = [];
54
+ /**
55
+ * The attribute of an option defines its ID
56
+ * @type {string}
57
+ */
58
+ export let idKey = "id";
59
+ /**
60
+ * The attribute of an option defines its label/name
61
+ * @type {string}
62
+ */
63
+ export let labelKey = "label";
64
+ /**
65
+ * Defines the width of the input in characters
66
+ * @type {number}
67
+ */
68
+ export let width = 30;
69
+ /**
70
+ * An array of colours for multi-select
71
+ * @type {array}
72
+ */
73
+ export let colors = [
74
+ "#206095",
75
+ "#a8bd3a",
76
+ "#871a5b",
77
+ "#27a0cc",
78
+ "rgb(0, 60, 87)",
79
+ "rgb(116, 108, 177)",
80
+ "rgb(246, 96, 104)",
81
+ "rgb(0, 163, 166)",
82
+ ];
83
+ /**
84
+ * A function to filter items based on the entered text
85
+ * @type {function}
86
+ */
87
+ export let itemFilter = (label, filterText, option) =>
88
+ label.match(new RegExp(`\\b${filterText}`, "i")) &&
89
+ !(multiple && value?.length >= maxSelected) &&
90
+ !(mode === "search" && filterText?.length < 3);
91
+ /**
92
+ * An optional function to load options based on the entered text
93
+ * @type {function}
94
+ */
95
+ export let loadOptions = null;
96
+ /**
97
+ * Optional params for positioning the dropdown
98
+ * @type {object} floatingConfig
99
+ */
100
+ export let floatingConfig = {};
101
+
102
+ $: style = colors.map((c, i) => `--item${i + 1}:${c}`).join(";");
103
+ $: noOptionsMessage =
104
+ multiple && value?.length >= maxSelected
105
+ ? `You can only select up to ${maxSelected} options`
106
+ : mode === "search" && filterText.length < 3
107
+ ? "Enter 3 or more characters to see options"
108
+ : filterText
109
+ ? `No options match <b>${filterText}</b>`
110
+ : "No options available";
111
+
112
+ let filterText = "";
113
+ </script>
114
+
115
+ <div class="ons-field" style="{style}">
116
+ {#if label}
117
+ <label class="ons-label" for="{id}" class:ons-u-vh="{hideLabel}">{label}</label>
118
+ {/if}
119
+ <div class="ons-themed-select {Number.isInteger(width) ? `ons-input--w-${width}` : ''}">
120
+ <SelectInner
121
+ id="{id}"
122
+ placeholder="{placeholder}"
123
+ loadOptions="{loadOptions}"
124
+ itemFilter="{itemFilter}"
125
+ floatingConfig="{floatingConfig}"
126
+ bind:filterText="{filterText}"
127
+ bind:value="{value}"
128
+ items="{options}"
129
+ itemId="{idKey}"
130
+ label="{labelKey}"
131
+ showChevron="{!value}"
132
+ multiple="{multiple}"
133
+ clearable="{clearable}"
134
+ on:input
135
+ on:change
136
+ on:focus
137
+ on:blur
138
+ on:clear
139
+ >
140
+ <div slot="item" let:item>
141
+ {@html item[labelKey].replace(
142
+ new RegExp(`\\b${filterText}`, "i"),
143
+ (str) => `<b>${str}</b>`
144
+ )}
145
+ </div>
146
+ <div slot="empty">{@html noOptionsMessage}</div>
147
+ <div slot="chevron-icon" style:transform="{mode === "search" ? "translateY(2px)" : null}">
148
+ {#if mode === "search"}
149
+ <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 12 12" width="20">
150
+ <path
151
+ fill="currentColor"
152
+ d="M11.86 10.23 8.62 6.99a4.63 4.63 0 1 0-6.34 1.64 4.55 4.55 0 0 0 2.36.64 4.65 4.65 0 0 0 2.33-.65l3.24 3.23a.46.46 0 0 0 .65 0l1-1a.48.48 0 0 0 0-.62Zm-5-3.32a3.28 3.28 0 0 1-2.31.93 3.22 3.22 0 1 1 2.35-.93Z"
153
+ ></path>
154
+ </svg>
155
+ {:else}
156
+ <svg
157
+ xmlns="http://www.w3.org/2000/svg"
158
+ aria-hidden="true"
159
+ viewBox="0 0 11.75 7.7"
160
+ width="18"
161
+ >
162
+ <path
163
+ fill="currentColor"
164
+ d="m1.37.15 4.5 5.1 4.5-5.1a.37.37 0 0 1 .6 0l.7.7a.45.45 0 0 1 0 .5l-5.5 6.2a.37.37 0 0 1-.6 0l-5.5-6.1a.64.64 0 0 1 0-.6l.7-.7a.64.64 0 0 1 .6 0Z"
165
+ ></path>
166
+ </svg>
167
+ {/if}
168
+ </div>
169
+ <div slot="clear-icon" style:transform="translateY(2px)">
170
+ <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" viewBox="0 0 14 14" width="18">
171
+ <path
172
+ fill="currentColor"
173
+ d="M13.6 1 l -0.71 -0.71 a 0.5 0.5 0 0 0 -0.71 0 l -5.25 5.25 l -5.25 -5.25 a 0.51 0.51 0 0 0 -0.71 0 l -0.71 0.71 a 0.5 0.5 0 0 0 0 0.71 l 5.25 5.25 l -5.25 5.25 a 0.5 0.5 0 0 0 0 0.71 l 0.71 0.71 a 0.5 0.5 0 0 0 0.71 0 l 5.25 -5.25 l 5.25 5.25 a 0.5 0.5 0 0 0 0.71 0 l 0.71 -0.71 a 0.5 0.5 0 0 0 0 -0.71 l -5.25 -5.25 l 5.25 -5.25 a 0.5 0.5 0 0 0 0 -0.71Z"
174
+ ></path>
175
+ </svg>
176
+ </div>
177
+ </SelectInner>
178
+ </div>
179
+ </div>
180
+
181
+ <style>
182
+ div[slot="empty"] {
183
+ background-color: rgb(226, 226, 227);
184
+ padding: 6px 10px;
185
+ }
186
+ .ons-themed-select {
187
+ --border: 1px solid currentColor;
188
+ --border-hover: 1px solid currentColor;
189
+ --border-focused: 1px solid currentColor;
190
+ --border-radius: 3px;
191
+ --font-size: 18px;
192
+ --placeholder-color: currentColor;
193
+ --padding: 0 0 0 10px;
194
+ --list-border: 1px solid currentColor;
195
+ --item-hover-bg: #003c57;
196
+ --item-hover-color: white;
197
+ --item-is-active-bg: #003c57;
198
+ --item-padding: 0 0 0 10px;
199
+ --multi-item-outline: none;
200
+ --multi-item-height: 30px;
201
+ --value-container-padding: 3px 0;
202
+ --multi-select-padding: 0 0 0 6px;
203
+ }
204
+ :global(.ons-themed-select > .svelte-select:focus-within) {
205
+ outline: 3px solid #fbc900;
206
+ }
207
+ :global(.ons-themed-select > .svelte-select:focus-within::before) {
208
+ content: "";
209
+ outline: 1px solid rgb(34, 34, 34);
210
+ outline-offset: -1px;
211
+ position: absolute;
212
+ width: 100%;
213
+ height: 100%;
214
+ left: 0;
215
+ pointer-events: none;
216
+ }
217
+ :global(.ons-themed-select .svelte-select-list) {
218
+ z-index: 4 !important;
219
+ color: #222;
220
+ }
221
+ :global(.ons-themed-select .svelte-select-list > div + div) {
222
+ border-top: 1px solid rgb(34, 34, 34);
223
+ }
224
+ :global(.ons-themed-select .multi-item) {
225
+ color: white !important;
226
+ font-weight: bold;
227
+ }
228
+ :global(.ons-themed-select .multi-item svg > path) {
229
+ fill: white !important;
230
+ }
231
+ :global(.ons-themed-select .multi-item:nth-of-type(1)) {
232
+ background-color: var(--item1, #ebedef) !important;
233
+ }
234
+ :global(.ons-themed-select .multi-item:nth-of-type(2)) {
235
+ background-color: var(--item2, #ebedef) !important;
236
+ }
237
+ :global(.ons-themed-select .multi-item:nth-of-type(3)) {
238
+ background-color: var(--item3, #ebedef) !important;
239
+ }
240
+ :global(.ons-themed-select .multi-item:nth-of-type(4)) {
241
+ background-color: var(--item4, #ebedef) !important;
242
+ }
243
+ :global(.ons-themed-select .multi-item:nth-of-type(5)) {
244
+ background-color: var(--item1, #ebedef) !important;
245
+ }
246
+ :global(.ons-themed-select .multi-item:nth-of-type(6)) {
247
+ background-color: var(--item2, #ebedef) !important;
248
+ }
249
+ :global(.ons-themed-select .multi-item:nth-of-type(7)) {
250
+ background-color: var(--item3, #ebedef) !important;
251
+ }
252
+ :global(.ons-themed-select .multi-item:nth-of-type(8)) {
253
+ background-color: var(--item4, #ebedef) !important;
254
+ }
255
+ .ons-field {
256
+ overflow: visible;
257
+ }</style>
@@ -0,0 +1,99 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+ const dispatch = createEventDispatcher();
5
+
6
+ /**
7
+ * ID for &lt;textarea&gt; element
8
+ * @type {string}
9
+ */
10
+ export let id = "";
11
+ /**
12
+ * A prop to bind to for the entered value
13
+ * @type {string}
14
+ */
15
+ export let value = "";
16
+ /**
17
+ * A label to describe the &lt;textarea&gt; element (expected for accessibility)
18
+ * @type {string}
19
+ */
20
+ export let label = "Enter some text";
21
+ /**
22
+ * Visually hide the label
23
+ * @type {boolean}
24
+ */
25
+ export let hideLabel = false;
26
+ /**
27
+ * An optional description to help users know what to enter
28
+ * @type {string}
29
+ */
30
+ export let description = "";
31
+ /**
32
+ * The maximum number of characters that can be entered (optional)
33
+ * @type {number}
34
+ */
35
+ export let charLimit = null;
36
+ /**
37
+ * The height of the &lt;textarea&gt; element in rows
38
+ * @type {number}
39
+ */
40
+ export let rows = 8;
41
+ /**
42
+ * The width of the &lt;textarea&gt; element in characters
43
+ * @type {number}
44
+ */
45
+ export let width = 30;
46
+
47
+ $: remaining = charLimit && value.length ? charLimit - value.length : charLimit || null;
48
+ </script>
49
+
50
+ <div class="ons-field">
51
+ {#if label}
52
+ <label
53
+ class="ons-label ons-label--with-description"
54
+ class:ons-u-vh="{hideLabel}"
55
+ aria-describedby="{description ? `${id}-description-hint` : null}"
56
+ for="{id}">{label}</label
57
+ >
58
+ {/if}
59
+ {#if description}
60
+ <span id="{id}-description-hint" class="ons-label__description ons-input--with-description"
61
+ >{description}</span
62
+ >
63
+ {/if}
64
+ <textarea
65
+ id="{id}"
66
+ bind:value="{value}"
67
+ class="ons-input ons-input--textarea {Number.isInteger(width) ? `ons-input--w-${width}` : null}"
68
+ class:ons-js-char-limit-input="{charLimit}"
69
+ class:ons-input--limit-reached="{remaining === 0}"
70
+ name="{id}"
71
+ rows="{rows}"
72
+ maxlength="{charLimit}"
73
+ data-char-limit-ref="{id}-lim"
74
+ aria-describedby="textarea-char-limit-lim"></textarea>
75
+ {#if Number.isInteger(remaining)}
76
+ <span
77
+ id="textarea-char-limit-lim"
78
+ class="ons-input__limit ons-u-fs-s--b ons-u-mt-xs"
79
+ class:ons-input__limit--reached="{remaining === 0}"
80
+ data-charcount-singular="You have {remaining} character remaining"
81
+ data-charcount-plural="You have {remaining} characters remaining"
82
+ data-charcount-limit-singular=""
83
+ data-charcount-limit-plural=""
84
+ aria-live="{remaining === 0 ? 'assertive' : 'polite'}"
85
+ >
86
+ You have {remaining}
87
+ {remaining === 1 ? "character" : "characters"} remaining
88
+ </span>
89
+ {/if}
90
+ </div>
91
+
92
+ <style>
93
+ .ons-input--textarea {
94
+ background: var(--background, white);
95
+ border-color: currentColor;
96
+ }
97
+ .ons-input--textarea:focus {
98
+ box-shadow: 0 0 0 1px currentColor, 0 0 0 4px #fbc900;
99
+ }</style>
@@ -0,0 +1,55 @@
1
+ @import url("https://cdn.ons.gov.uk/sdc/design-system/64.0.0/css/main.css");
2
+ @import url("https://cdn.ons.gov.uk/dp-design-system/cc82c54/css/main.css");
3
+
4
+ /* Overrides */
5
+ .ons-page__content {
6
+ padding-bottom: 0;
7
+ }
8
+
9
+ /* Theme settings */
10
+ html,
11
+ body {
12
+ --text: #222;
13
+ --muted: #777;
14
+ --hinted: #e2e2e3;
15
+ --pale: #f0f0f0;
16
+ --background: #fff;
17
+ --link: #206095;
18
+ --link-hover: #003c57;
19
+ }
20
+ .theme-wrapper {
21
+ color: var(--text);
22
+ background: var(--background);
23
+ --ons-color-text: var(--text);
24
+ --ons-color-text-light: var(--muted);
25
+ --ons-color-borders: var(--muted);
26
+ }
27
+ a {
28
+ color: var(--link, --ons-color-text-link);
29
+ }
30
+ a:hover {
31
+ text-decoration: underline solid
32
+ var(--link-hover, --ons-color-text-link-hover) 2px;
33
+ }
34
+ a:hover {
35
+ color: var(--link-hover, --ons-color-text-link-hover);
36
+ }
37
+ .form-label-bold {
38
+ color: var(--text, #222);
39
+ }
40
+ .form-control {
41
+ background: none;
42
+ border-color: var(--text, #222);
43
+ color: var(--text, #222);
44
+ }
45
+
46
+ /* Additional global styles */
47
+ .ons-spacer {
48
+ display: block;
49
+ height: 40px;
50
+ margin: 0;
51
+ padding: 0;
52
+ }
53
+ .ons-font-weight__normal {
54
+ font-weight: normal;
55
+ }
@@ -0,0 +1,23 @@
1
+ interface ChartbeatConfig {
2
+ uid?: number;
3
+ domain?: string;
4
+ flickerControl?: boolean;
5
+ useCanonical?: boolean;
6
+ useCanonicalDomain?: boolean;
7
+ sections?: string;
8
+ authors?: string;
9
+ }
10
+
11
+ declare global {
12
+ // eslint-disable-next-line no-unused-vars
13
+ interface Window {
14
+ /** Google analytics dataLayer */
15
+ dataLayer: Record<string, any>,
16
+ /** Chartbeat config */
17
+ _sf_async_config: ChartbeatConfig,
18
+ /** Chartbeat method */
19
+ pSUPERFLY: (config: { path: string, title: string }) => void,
20
+ }
21
+ }
22
+
23
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // Layout
2
+ export { default as Accordion } from "./components/layout/Accordion/Accordion.svelte";
3
+ export { default as Container } from "./components/layout/Container/Container.svelte";
4
+ export { default as Footer } from "./components/layout/Footer/Footer.svelte";
5
+ export { default as Header } from "./components/layout/Header/Header.svelte";
6
+ export { default as Section } from "./components/layout/Section/Section.svelte";
7
+ export { default as Theme } from "./components/layout/Theme/Theme.svelte";
8
+ export { default as Twisty } from "./components/layout/Twisty/Twisty.svelte";
9
+
10
+ // UI
11
+ export { default as Button } from "./components/ui/Button/Button.svelte";
12
+ export { default as Dropdown } from "./components/ui/Dropdown/Dropdown.svelte";
13
+ export { default as Em } from "./components/ui/Em/Em.svelte";
14
+ export { default as Input } from "./components/ui/Input/Input.svelte";
15
+ export { default as Select } from "./components/ui/Select/Select.svelte";
16
+ export { default as Textarea } from "./components/ui/Textarea/Textarea.svelte";
@@ -0,0 +1,41 @@
1
+ // const randomString = () => {
2
+ // return Math.random().toString(16).slice(2, 8);
3
+ // };
4
+
5
+ export const slugify = (str, suffix = true) =>
6
+ str
7
+ .toString()
8
+ .normalize("NFD")
9
+ .replace(/[\u0300-\u036f]/g, "")
10
+ .toLowerCase()
11
+ .trim()
12
+ .replace(/\s+/g, "-")
13
+ .replace(/[^\w-]+/g, "")
14
+ .replace(/--+/g, "-");
15
+ // .concat(suffix ? `-${randomString()}` : "");
16
+
17
+ export const validDate = (str) => {
18
+ const date = new Date(str);
19
+ return !isNaN(date);
20
+ };
21
+
22
+ export const formatDate = (
23
+ str,
24
+ locale = "en-GB",
25
+ opts = { year: "numeric", month: "long", day: "2-digit" }
26
+ ) => {
27
+ const date = new Date(str);
28
+ return date.toLocaleDateString(locale, opts);
29
+ };
30
+
31
+ export const commas = (num) => {
32
+ const parts = String(num).split(".");
33
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
34
+ return parts.join(".");
35
+ };
36
+
37
+ export const ascending = (a, b) =>
38
+ a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
39
+
40
+ export const descending = (a, b) =>
41
+ a == null || b == null ? NaN : b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;