@hyvor/design 2.1.8-beta.5 → 2.1.9

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 (64) hide show
  1. package/dist/cloud/HyvorBar/BarNotice/BarNotice.svelte +1 -1
  2. package/dist/cloud/HyvorBar/BarSupport.svelte +1 -1
  3. package/dist/cloud/HyvorBar/Organization/BarOrganization.svelte +1 -1
  4. package/dist/components/Avatar/Avatar.svelte +50 -4
  5. package/dist/components/Avatar/Avatar.svelte.d.ts +4 -1
  6. package/dist/components/Avatar/AvatarStack.svelte +6 -3
  7. package/dist/components/ButtonGroup/ButtonGroup.svelte +82 -0
  8. package/dist/components/{Button → ButtonGroup}/ButtonGroup.svelte.d.ts +1 -0
  9. package/dist/components/Modal/ConfirmModalProvider.svelte +6 -9
  10. package/dist/components/Modal/ModalFooter.svelte +24 -27
  11. package/dist/components/Toast/ToastMessage.svelte +3 -6
  12. package/dist/components/Toast/ToastProvider.svelte +8 -4
  13. package/dist/components/Tooltip/Tooltip.svelte +54 -28
  14. package/dist/components/Tooltip/Tooltip.svelte.d.ts +15 -35
  15. package/dist/components/index.d.ts +1 -1
  16. package/dist/components/index.js +1 -1
  17. package/dist/index.css +4 -1
  18. package/dist/marketing/Docs/Docs.svelte +2 -2
  19. package/dist/marketing/Footer/Footer.svelte +98 -402
  20. package/dist/marketing/Footer/Footer.svelte.d.ts +2 -18
  21. package/dist/marketing/Footer/FooterLinkList.svelte +3 -10
  22. package/dist/marketing/Header/Header.svelte +28 -72
  23. package/dist/marketing/Header/Header.svelte.d.ts +2 -5
  24. package/dist/marketing/index.d.ts +0 -18
  25. package/dist/marketing/index.js +0 -17
  26. package/dist/marketing/social.d.ts +1 -1
  27. package/dist/marketing/social.js +1 -1
  28. package/package.json +1 -1
  29. package/dist/components/Button/ButtonGroup.svelte +0 -18
  30. package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordion.svelte +0 -251
  31. package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordion.svelte.d.ts +0 -23
  32. package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte +0 -75
  33. package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte.d.ts +0 -10
  34. package/dist/marketing/FAQ/FAQ.svelte +0 -233
  35. package/dist/marketing/FAQ/FAQ.svelte.d.ts +0 -13
  36. package/dist/marketing/FeatureSplit/FeatureSplit.svelte +0 -325
  37. package/dist/marketing/FeatureSplit/FeatureSplit.svelte.d.ts +0 -24
  38. package/dist/marketing/FullTrialSignup/FullTrialSignup.svelte +0 -164
  39. package/dist/marketing/FullTrialSignup/FullTrialSignup.svelte.d.ts +0 -18
  40. package/dist/marketing/Header/HeaderLanguageToggle.svelte +0 -121
  41. package/dist/marketing/Header/HeaderLanguageToggle.svelte.d.ts +0 -14
  42. package/dist/marketing/Header/HeaderNavLink.svelte +0 -148
  43. package/dist/marketing/Header/HeaderNavLink.svelte.d.ts +0 -17
  44. package/dist/marketing/Header/language.d.ts +0 -18
  45. package/dist/marketing/Header/language.js +0 -35
  46. package/dist/marketing/Hero/Hero.svelte +0 -353
  47. package/dist/marketing/Hero/Hero.svelte.d.ts +0 -16
  48. package/dist/marketing/LogoStrip/LogoStrip.svelte +0 -204
  49. package/dist/marketing/LogoStrip/LogoStrip.svelte.d.ts +0 -19
  50. package/dist/marketing/Seal/CcpaSeal.svelte +0 -29
  51. package/dist/marketing/Seal/CcpaSeal.svelte.d.ts +0 -6
  52. package/dist/marketing/Seal/GdprSeal.svelte +0 -60
  53. package/dist/marketing/Seal/GdprSeal.svelte.d.ts +0 -6
  54. package/dist/marketing/Seal/IsoSeal.svelte +0 -44
  55. package/dist/marketing/Seal/IsoSeal.svelte.d.ts +0 -6
  56. package/dist/marketing/Seal/Seal.svelte +0 -62
  57. package/dist/marketing/Seal/Seal.svelte.d.ts +0 -8
  58. package/dist/marketing/Seal/SsoSeal.svelte +0 -31
  59. package/dist/marketing/Seal/SsoSeal.svelte.d.ts +0 -6
  60. package/dist/marketing/Seal/ccpa.svg +0 -131
  61. package/dist/marketing/SpotlightSplit/SpotlightSplit.svelte +0 -256
  62. package/dist/marketing/SpotlightSplit/SpotlightSplit.svelte.d.ts +0 -19
  63. package/dist/marketing/Testimonials/Testimonials.svelte +0 -382
  64. package/dist/marketing/Testimonials/Testimonials.svelte.d.ts +0 -23
@@ -1,233 +0,0 @@
1
- <script lang="ts">
2
- interface FaqItem {
3
- q: string;
4
- /** answer content as HTML — also used verbatim as the rich schema's answer text */
5
- a: string;
6
- }
7
-
8
- interface Props {
9
- items: FaqItem[];
10
- columns?: 1 | 2;
11
- // emit the FAQPage JSON-LD rich schema into <svelte:head>
12
- richSchema?: boolean;
13
- }
14
-
15
- let { items, columns = 2, richSchema = true }: Props = $props();
16
-
17
- const uid = $props.id();
18
-
19
- // which items go in which column (left-to-right, top-to-bottom within each column),
20
- // carrying each item's original index along so column splitting doesn't affect it
21
- const cols = $derived.by(() => {
22
- const indexed = items.map((item, index) => ({ item, index }));
23
- if (columns === 1) return [indexed];
24
- const mid = Math.ceil(indexed.length / 2);
25
- return [indexed.slice(0, mid), indexed.slice(mid)];
26
- });
27
-
28
- // independent open/close state per item, first one open by default
29
- let openStates = $state(items.map((_, i) => i === 0));
30
-
31
- function toggle(i: number) {
32
- openStates[i] = !openStates[i];
33
- }
34
-
35
- // FAQPage rich schema, generated straight from the same array that renders the accordion
36
- // (Google's FAQPage guidelines allow a limited set of formatting HTML in the answer text)
37
- const richSchemaObj = $derived({
38
- '@context': 'https://schema.org',
39
- '@type': 'FAQPage',
40
- mainEntity: items.map((item) => ({
41
- '@type': 'Question',
42
- name: item.q,
43
- acceptedAnswer: {
44
- '@type': 'Answer',
45
- text: item.a
46
- }
47
- }))
48
- });
49
-
50
- const richSchemaScript = $derived(
51
- '<' + 'script type="application/ld+json">' + JSON.stringify(richSchemaObj) + '<' + '/script>'
52
- );
53
- </script>
54
-
55
- <svelte:head>
56
- {#if richSchema}
57
- {@html richSchemaScript}
58
- {/if}
59
- </svelte:head>
60
-
61
- <div class="hds-faq" class:single={columns === 1}>
62
- {#each cols as col, colIndex (colIndex)}
63
- <div class="faq-col">
64
- {#each col as { item, index } (item.q)}
65
- <div class="faq" class:open={openStates[index]}>
66
- <h3 class="heading">
67
- <button
68
- class="trigger"
69
- id="hds-faq-trigger-{uid}-{index}"
70
- onclick={() => toggle(index)}
71
- aria-expanded={openStates[index]}
72
- aria-controls="hds-faq-panel-{uid}-{index}"
73
- >
74
- <span class="q">{item.q}</span>
75
- <span class="toggle-icon" aria-hidden="true">
76
- <span class="line horizontal"></span>
77
- <span class="line vertical"></span>
78
- </span>
79
- </button>
80
- </h3>
81
-
82
- <div
83
- class="body"
84
- class:open={openStates[index]}
85
- role="region"
86
- id="hds-faq-panel-{uid}-{index}"
87
- aria-labelledby="hds-faq-trigger-{uid}-{index}"
88
- >
89
- <div class="body-inner">
90
- <div class="a">{@html item.a}</div>
91
- </div>
92
- </div>
93
- </div>
94
- {/each}
95
- </div>
96
- {/each}
97
- </div>
98
-
99
- <style>
100
- .hds-faq {
101
- display: flex;
102
- gap: 0 60px;
103
- }
104
-
105
- .hds-faq.single {
106
- display: block;
107
- }
108
-
109
- .faq-col {
110
- flex: 1;
111
- min-width: 0;
112
- }
113
-
114
- .faq {
115
- border-bottom: 1px solid var(--border);
116
- }
117
-
118
- .heading {
119
- margin: 0;
120
- font-size: inherit;
121
- font-weight: inherit;
122
- }
123
-
124
- .trigger {
125
- display: flex;
126
- align-items: center;
127
- justify-content: space-between;
128
- gap: 20px;
129
- width: 100%;
130
- padding: 20px 0;
131
- background: none;
132
- border: none;
133
- cursor: pointer;
134
- text-align: left;
135
- color: inherit;
136
- font: inherit;
137
- }
138
-
139
- .q {
140
- font-size: 16px;
141
- font-weight: 600;
142
- letter-spacing: -0.01em;
143
- }
144
-
145
- .toggle-icon {
146
- position: relative;
147
- flex-shrink: 0;
148
- width: 24px;
149
- height: 24px;
150
- border-radius: 50%;
151
- background: var(--accent-light-mid);
152
- color: var(--accent);
153
- transition: transform 0.3s cubic-bezier(0.65, 0, 0.35, 1);
154
- }
155
-
156
- .faq.open .toggle-icon {
157
- transform: rotate(180deg);
158
- }
159
-
160
- .line {
161
- position: absolute;
162
- top: 50%;
163
- left: 50%;
164
- background: currentColor;
165
- border-radius: 2px;
166
- transform: translate(-50%, -50%);
167
- transition:
168
- transform 0.3s cubic-bezier(0.65, 0, 0.35, 1),
169
- opacity 0.2s ease;
170
- }
171
-
172
- .line.horizontal {
173
- width: 12px;
174
- height: 2px;
175
- }
176
-
177
- .line.vertical {
178
- width: 2px;
179
- height: 12px;
180
- }
181
-
182
- .faq.open .line.vertical {
183
- transform: translate(-50%, -50%) rotate(90deg);
184
- opacity: 0;
185
- }
186
-
187
- /* CSS grid row trick: content stays in DOM for SEO, height animates via grid */
188
- .body {
189
- display: grid;
190
- grid-template-rows: 0fr;
191
- transition: grid-template-rows 0.3s cubic-bezier(0.65, 0, 0.35, 1);
192
- }
193
-
194
- .body.open {
195
- grid-template-rows: 1fr;
196
- }
197
-
198
- .body-inner {
199
- overflow: hidden;
200
- }
201
-
202
- .a {
203
- padding: 0 30px 22px 0;
204
- font-size: 15px;
205
- line-height: 1.6;
206
- color: var(--text-light);
207
- opacity: 0;
208
- transform: translateY(-6px);
209
- transition:
210
- opacity 0.25s ease,
211
- transform 0.25s ease;
212
- }
213
-
214
- .body.open .a {
215
- opacity: 1;
216
- transform: translateY(0);
217
- transition-delay: 0.08s;
218
- }
219
-
220
- /* answers are raw HTML (@html) — style plain <a> tags to match the design
221
- system's Link component, which snippet-based answers would use */
222
- .a :global(a) {
223
- color: var(--link);
224
- text-decoration: underline;
225
- }
226
-
227
- @media (max-width: 768px) {
228
- .hds-faq {
229
- flex-direction: column;
230
- gap: 0;
231
- }
232
- }
233
- </style>
@@ -1,13 +0,0 @@
1
- interface FaqItem {
2
- q: string;
3
- /** answer content as HTML — also used verbatim as the rich schema's answer text */
4
- a: string;
5
- }
6
- interface Props {
7
- items: FaqItem[];
8
- columns?: 1 | 2;
9
- richSchema?: boolean;
10
- }
11
- declare const FAQ: import("svelte").Component<Props, {}, "">;
12
- type FAQ = ReturnType<typeof FAQ>;
13
- export default FAQ;
@@ -1,325 +0,0 @@
1
- <script lang="ts">
2
- import Button from '../../components/Button/Button.svelte';
3
- import IconBoxArrowUpRight from '@hyvor/icons/IconBoxArrowUpRight';
4
- import IconCheckCircleFill from '@hyvor/icons/IconCheckCircleFill';
5
- import type { Snippet } from 'svelte';
6
-
7
- type ButtonConfig = { href: string; label: string; external?: boolean };
8
-
9
- interface Props {
10
- eyebrow: string;
11
- title: string | Snippet;
12
- description: string;
13
- bullets?: string[] | Snippet;
14
- button?: ButtonConfig | ButtonConfig[] | null;
15
- flip?: boolean;
16
- altBg?: boolean;
17
- overlap?: boolean;
18
- interactiveBullets?: boolean;
19
- visual: Snippet<[activeBullet: number]>;
20
- after?: Snippet;
21
- left?: Snippet;
22
- max?: boolean;
23
- }
24
-
25
- let {
26
- eyebrow,
27
- title,
28
- description,
29
- bullets = [],
30
- button = null,
31
- flip = false,
32
- altBg = false,
33
- overlap = false,
34
- interactiveBullets = false,
35
- visual,
36
- after,
37
- left,
38
- max = false
39
- }: Props = $props();
40
-
41
- let inView = $state(false);
42
- let activeBullet = $state(0);
43
-
44
- // how long the active bullet's progress bar takes to fill before auto-advancing
45
- const AUTO_ADVANCE_MS = 5000;
46
-
47
- $effect(() => {
48
- if (!interactiveBullets || !inView) return;
49
- if (!Array.isArray(bullets) || bullets.length <= 1) return;
50
- activeBullet;
51
- const count = bullets.length;
52
- const timer = setTimeout(() => {
53
- activeBullet = (activeBullet + 1) % count;
54
- }, AUTO_ADVANCE_MS);
55
- return () => clearTimeout(timer);
56
- });
57
-
58
- function onView(node: HTMLElement, callback: () => void) {
59
- const observer = new IntersectionObserver(
60
- (entries) => {
61
- if (entries[0]?.isIntersecting) {
62
- callback();
63
- observer.disconnect();
64
- }
65
- },
66
- { threshold: 0.25 }
67
- );
68
- observer.observe(node);
69
- return {
70
- destroy() {
71
- observer.disconnect();
72
- }
73
- };
74
- }
75
- </script>
76
-
77
- <section class="hds-feature-split" class:alt-bg={altBg}>
78
- <div class={max ? 'hds-container-max split' : 'hds-container split'} class:flip class:overlap>
79
- <div class="text-col" class:in-view={inView} use:onView={() => (inView = true)}>
80
- {#if left}
81
- {@render left()}
82
- {:else}
83
- <span class="eyebrow">{eyebrow}</span>
84
- <h2>
85
- {#if typeof title === 'string'}
86
- {@html title}
87
- {:else}
88
- {@render title()}
89
- {/if}
90
- </h2>
91
- <p>{description}</p>
92
-
93
- {#if Array.isArray(bullets)}
94
- {#if bullets.length}
95
- <ul class="bullets" class:interactive={interactiveBullets}>
96
- {#each bullets as b, i}
97
- <li>
98
- {#if interactiveBullets}
99
- <button
100
- type="button"
101
- class="bullet-btn"
102
- class:active={activeBullet === i}
103
- style="animation-duration: {AUTO_ADVANCE_MS}ms"
104
- onclick={() => (activeBullet = i)}
105
- >
106
- <IconCheckCircleFill size={14} />{b}
107
- </button>
108
- {:else}
109
- <IconCheckCircleFill size={14} />{b}
110
- {/if}
111
- </li>
112
- {/each}
113
- </ul>
114
- {/if}
115
- {:else if bullets}
116
- {@render bullets()}
117
- {/if}
118
-
119
- {#if button}
120
- {@const buttons = Array.isArray(button) ? button : [button]}
121
- <div class="buttons">
122
- {#each buttons as b}
123
- <Button
124
- as="a"
125
- href={b.href}
126
- target={b.external ? '_blank' : undefined}
127
- rel={b.external ? 'noopener' : undefined}
128
- variant="outline"
129
- size="small"
130
- >
131
- {b.label}
132
- {#snippet end()}<IconBoxArrowUpRight size={11} />{/snippet}
133
- </Button>
134
- {/each}
135
- </div>
136
- {/if}
137
- {/if}
138
- </div>
139
-
140
- <div class="visual-col">
141
- {@render visual(activeBullet)}
142
- </div>
143
- </div>
144
-
145
- {#if after}
146
- <div class="hds-container-max">
147
- {@render after()}
148
- </div>
149
- {/if}
150
- </section>
151
-
152
- <style>
153
- .hds-feature-split {
154
- padding: 100px 0;
155
- overflow-x: hidden;
156
- }
157
-
158
- .alt-bg {
159
- background: color-mix(in srgb, var(--accent) 10%, var(--background));
160
- }
161
-
162
- .split {
163
- display: flex;
164
- align-items: center;
165
- gap: 72px;
166
- }
167
-
168
- .split.flip {
169
- flex-direction: row-reverse;
170
- }
171
-
172
- .text-col,
173
- .visual-col {
174
- flex: 1;
175
- min-width: 0;
176
- }
177
-
178
- .text-col {
179
- opacity: 0;
180
- transform: translateY(18px);
181
- transition:
182
- opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
183
- transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
184
- }
185
-
186
- .text-col.in-view {
187
- opacity: 1;
188
- transform: none;
189
- }
190
- .split.overlap .text-col {
191
- z-index: 2;
192
- }
193
-
194
- .eyebrow {
195
- display: inline-block;
196
- font-size: 12px;
197
- font-weight: 700;
198
- letter-spacing: 0.1em;
199
- text-transform: uppercase;
200
- color: var(--accent);
201
- margin-bottom: 16px;
202
- }
203
-
204
- h2 {
205
- font-size: clamp(26px, 3.5vw, 38px);
206
- font-weight: 800;
207
- letter-spacing: -0.02em;
208
- line-height: 1.15;
209
- margin: 0 0 16px;
210
- }
211
-
212
- p {
213
- font-size: 16px;
214
- line-height: 1.7;
215
- color: var(--text-light);
216
- margin: 0 0 28px;
217
- max-width: 440px;
218
- }
219
-
220
- .bullets {
221
- list-style: none;
222
- margin: 0 0 32px;
223
- padding: 0;
224
- display: flex;
225
- flex-direction: column;
226
- gap: 10px;
227
- }
228
-
229
- .bullets li {
230
- display: flex;
231
- align-items: flex-start;
232
- gap: 10px;
233
- font-size: 1rem;
234
- text-align: left;
235
- }
236
-
237
- .bullets li :global(svg) {
238
- color: var(--accent);
239
- flex-shrink: 0;
240
- margin-top: 0.3em;
241
- }
242
-
243
- .bullet-btn {
244
- position: relative;
245
- display: flex;
246
- align-items: flex-start;
247
- gap: 10px;
248
- width: 100%;
249
- padding: 8px 10px;
250
- border: none;
251
- border-radius: 20px;
252
- background-color: transparent;
253
- background-image: linear-gradient(
254
- color-mix(in srgb, var(--accent) 14%, transparent),
255
- color-mix(in srgb, var(--accent) 14%, transparent)
256
- );
257
- background-repeat: no-repeat;
258
- background-position: left center;
259
- background-size: 0% 100%;
260
- color: var(--text-light);
261
- font: inherit;
262
- font-size: 1rem;
263
- text-align: left;
264
- cursor: pointer;
265
- transition:
266
- background-color 0.2s,
267
- color 0.2s;
268
- }
269
-
270
- .bullet-btn:hover {
271
- background-color: color-mix(in srgb, var(--text) 4%, transparent);
272
- }
273
-
274
- .bullet-btn.active {
275
- color: var(--text);
276
- animation-name: bullet-fill;
277
- animation-timing-function: linear;
278
- animation-fill-mode: forwards;
279
- }
280
-
281
- @keyframes bullet-fill {
282
- from {
283
- background-size: 0% 100%;
284
- }
285
- to {
286
- background-size: 100% 100%;
287
- }
288
- }
289
-
290
- .bullets.interactive li :global(svg) {
291
- color: var(--text-light);
292
- }
293
-
294
- .bullets.interactive li:has(.bullet-btn.active) :global(svg) {
295
- color: var(--accent);
296
- }
297
-
298
- .buttons {
299
- display: flex;
300
- flex-wrap: wrap;
301
- gap: 12px;
302
- }
303
-
304
- @media (max-width: 900px) {
305
- .split,
306
- .split.flip {
307
- flex-direction: column;
308
- align-items: stretch;
309
- gap: 48px;
310
- }
311
-
312
- .text-col {
313
- width: 100%;
314
- text-align: left;
315
- }
316
-
317
- .visual-col {
318
- width: 100%;
319
- }
320
-
321
- p {
322
- max-width: 100%;
323
- }
324
- }
325
- </style>
@@ -1,24 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- type ButtonConfig = {
3
- href: string;
4
- label: string;
5
- external?: boolean;
6
- };
7
- interface Props {
8
- eyebrow: string;
9
- title: string | Snippet;
10
- description: string;
11
- bullets?: string[] | Snippet;
12
- button?: ButtonConfig | ButtonConfig[] | null;
13
- flip?: boolean;
14
- altBg?: boolean;
15
- overlap?: boolean;
16
- interactiveBullets?: boolean;
17
- visual: Snippet<[activeBullet: number]>;
18
- after?: Snippet;
19
- left?: Snippet;
20
- max?: boolean;
21
- }
22
- declare const FeatureSplit: import("svelte").Component<Props, {}, "">;
23
- type FeatureSplit = ReturnType<typeof FeatureSplit>;
24
- export default FeatureSplit;