@jelinek/ui 0.3.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 (84) hide show
  1. package/README.md +492 -0
  2. package/dist/components/Alert.svelte +59 -0
  3. package/dist/components/Alert.svelte.d.ts +13 -0
  4. package/dist/components/Button.svelte +178 -0
  5. package/dist/components/Button.svelte.d.ts +19 -0
  6. package/dist/components/Card.svelte +68 -0
  7. package/dist/components/Card.svelte.d.ts +11 -0
  8. package/dist/components/ChapterNav.svelte +290 -0
  9. package/dist/components/ChapterNav.svelte.d.ts +18 -0
  10. package/dist/components/Checkbox.svelte +52 -0
  11. package/dist/components/Checkbox.svelte.d.ts +11 -0
  12. package/dist/components/CodeCopy.svelte +294 -0
  13. package/dist/components/CodeCopy.svelte.d.ts +51 -0
  14. package/dist/components/Container.svelte +34 -0
  15. package/dist/components/Container.svelte.d.ts +10 -0
  16. package/dist/components/ContentLogo.svelte +151 -0
  17. package/dist/components/ContentLogo.svelte.d.ts +37 -0
  18. package/dist/components/Demo.svelte +111 -0
  19. package/dist/components/Demo.svelte.d.ts +12 -0
  20. package/dist/components/Eyebrow.svelte +70 -0
  21. package/dist/components/Eyebrow.svelte.d.ts +12 -0
  22. package/dist/components/Glass.svelte +75 -0
  23. package/dist/components/Glass.svelte.d.ts +10 -0
  24. package/dist/components/Grid.svelte +87 -0
  25. package/dist/components/Grid.svelte.d.ts +11 -0
  26. package/dist/components/Label.svelte +37 -0
  27. package/dist/components/Label.svelte.d.ts +11 -0
  28. package/dist/components/PageHero.svelte +312 -0
  29. package/dist/components/PageHero.svelte.d.ts +55 -0
  30. package/dist/components/Pager.svelte +98 -0
  31. package/dist/components/Pager.svelte.d.ts +13 -0
  32. package/dist/components/Panel.svelte +89 -0
  33. package/dist/components/Panel.svelte.d.ts +12 -0
  34. package/dist/components/ProductCard.svelte +81 -0
  35. package/dist/components/ProductCard.svelte.d.ts +18 -0
  36. package/dist/components/Radio.svelte +54 -0
  37. package/dist/components/Radio.svelte.d.ts +11 -0
  38. package/dist/components/RadioGroup.svelte +42 -0
  39. package/dist/components/RadioGroup.svelte.d.ts +12 -0
  40. package/dist/components/Select.svelte +65 -0
  41. package/dist/components/Select.svelte.d.ts +20 -0
  42. package/dist/components/SiteFooter.svelte +121 -0
  43. package/dist/components/SiteFooter.svelte.d.ts +13 -0
  44. package/dist/components/SiteHeader.svelte +613 -0
  45. package/dist/components/SiteHeader.svelte.d.ts +80 -0
  46. package/dist/components/Slider.svelte +55 -0
  47. package/dist/components/Slider.svelte.d.ts +14 -0
  48. package/dist/components/Swatch.svelte +174 -0
  49. package/dist/components/Swatch.svelte.d.ts +58 -0
  50. package/dist/components/Tab.svelte +88 -0
  51. package/dist/components/Tab.svelte.d.ts +11 -0
  52. package/dist/components/Tabs.svelte +306 -0
  53. package/dist/components/Tabs.svelte.d.ts +20 -0
  54. package/dist/components/Tag.svelte +71 -0
  55. package/dist/components/Tag.svelte.d.ts +16 -0
  56. package/dist/components/TextField.svelte +100 -0
  57. package/dist/components/TextField.svelte.d.ts +18 -0
  58. package/dist/components/ThemeToggle.svelte +122 -0
  59. package/dist/components/ThemeToggle.svelte.d.ts +11 -0
  60. package/dist/components/Tile.svelte +115 -0
  61. package/dist/components/Tile.svelte.d.ts +14 -0
  62. package/dist/components/TileScroller.svelte +199 -0
  63. package/dist/components/TileScroller.svelte.d.ts +25 -0
  64. package/dist/components/container-context.d.ts +1 -0
  65. package/dist/components/container-context.js +6 -0
  66. package/dist/components/deer-mark-path.d.ts +16 -0
  67. package/dist/components/deer-mark-path.js +16 -0
  68. package/dist/components/nav.d.ts +25 -0
  69. package/dist/components/nav.js +17 -0
  70. package/dist/components/radio-context.d.ts +6 -0
  71. package/dist/components/radio-context.js +1 -0
  72. package/dist/components/tabs-context.d.ts +5 -0
  73. package/dist/components/tabs-context.js +1 -0
  74. package/dist/index.d.ts +37 -0
  75. package/dist/index.js +37 -0
  76. package/dist/theme/base.css +439 -0
  77. package/dist/theme/extras.css +2 -0
  78. package/dist/theme/fonts.css +107 -0
  79. package/dist/theme/tokens.css +208 -0
  80. package/dist/utils/chapter-nav-dock.svelte.d.ts +23 -0
  81. package/dist/utils/chapter-nav-dock.svelte.js +65 -0
  82. package/dist/utils/cn.d.ts +2 -0
  83. package/dist/utils/cn.js +27 -0
  84. package/package.json +79 -0
@@ -0,0 +1,115 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAnchorAttributes, HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../utils/cn.js';
5
+
6
+ type Color = 'brown' | 'magenta';
7
+
8
+ interface Props {
9
+ href?: string;
10
+ active?: boolean;
11
+ color?: Color;
12
+ class?: string;
13
+ children: Snippet;
14
+ }
15
+
16
+ let {
17
+ href,
18
+ active = false,
19
+ color = 'brown',
20
+ class: className,
21
+ children,
22
+ ...rest
23
+ }: Props & Omit<HTMLAnchorAttributes & HTMLAttributes<HTMLDivElement>, 'href'> = $props();
24
+
25
+ const ACTIVE: Record<Color, string> = {
26
+ brown: 'border-jelinek-brown bg-surface-brown',
27
+ magenta: 'border-jelinek-magenta bg-surface-magenta'
28
+ };
29
+
30
+ // jelinek.css:474-481 (shared surface, --box-accent unset by .tile so it
31
+ // defaults to --border-subtle at both gradient stops) collapses to a flat
32
+ // 1px border-border-subtle, same reasoning as Card. jelinek.css:641-649
33
+ // (.tile): padding is 22px, NOT 24px — p-6 was wrong, this is the arbitrary
34
+ // p-[22px] (tile deliberately has its own padding, distinct from
35
+ // .panel/.card/.demo's 24px, and — unlike those three — carries no
36
+ // margin-bottom of its own to drop). color:var(--text-black) was missing
37
+ // entirely (text-fg). box-shadow:var(--shadow-resting) at rest was missing
38
+ // entirely; only the :hover shadow-interactive had been kept, with no
39
+ // resting state to raise it from. jelinek.css:322-325 (shared surface
40
+ // block) puts .tile — explicitly listed alongside .card/.panel/.alert/
41
+ // .demo/.swatch — on font-secondary at font-weight 300 (Light), which the
42
+ // draft omitted altogether in favour of a plain "font-normal" (400).
43
+ // That 400 traces to jelinek.css:285's `.tile, .pager a { font-weight:
44
+ // 400 }`, whose real job is neutralising the global `a { font-weight:
45
+ // 700 }` bold — but :322-325 is later in the file at equal specificity
46
+ // (single class selector, same as :285's `.tile`) and so is the value
47
+ // that actually wins the cascade: font-light, not font-normal.
48
+ // jelinek.css:327-331 additionally raises nested strong/b back to
49
+ // font-weight 500, and :648/:652 give a Tile's own h3/p their own spacing
50
+ // and size (h3: 6px bottom margin + --step1 size/1.3 line-height; p: 0
51
+ // margin, 0.9rem, --text-muted1). Tile's children are an opaque Snippet,
52
+ // so these are reproduced as compound arbitrary variants on the root
53
+ // element rather than as JSX/markup this component controls directly —
54
+ // Card did not do this for its own equivalent h3/strong/b rules (Task 5),
55
+ // so this is a deliberate inconsistency between the two components,
56
+ // flagged for adjudication: either Card should get the same treatment
57
+ // later, or this should be dropped from Tile to match Card's precedent.
58
+ // Task 31 — the transition is the guide's own two properties and its own
59
+ // duration/easing tokens (jelinek.css:924: `transition: box-shadow
60
+ // var(--dur-base) var(--ease), transform var(--dur-base) var(--ease)`),
61
+ // replacing a bare `transition-all`. That matters here beyond tidiness:
62
+ // `.tile.is-active` (jelinek.css:927) flips border-color AND background, and
63
+ // `transition-all` was fading both of those too, which the guide never does
64
+ // — an active tile now snaps to its brown state and only the shadow/lift
65
+ // animate. See Button.svelte's own comment for why --ease has to be named
66
+ // explicitly (Tailwind's default curve is not the guide's `ease`) and why
67
+ // this is not solved globally in extras.css.
68
+ const BASE =
69
+ 'block rounded-card border border-border-subtle bg-surface p-[22px] ' +
70
+ 'font-secondary font-light text-fg no-underline ' +
71
+ 'transition-[box-shadow,transform] duration-[var(--dur-base)] ease-[var(--ease)] ' +
72
+ 'shadow-resting hover:-translate-y-0.5 hover:shadow-interactive ' +
73
+ '[&_h3]:mb-1.5 [&_h3]:text-step1 [&_h3]:leading-[1.3] ' +
74
+ '[&_p]:m-0 [&_p]:text-[0.9rem] [&_p]:text-fg-muted1 ' +
75
+ '[&_strong]:font-medium [&_b]:font-medium ' +
76
+ // jelinek.css:259-260 (dark mode only): the resting/hover shadow gains an
77
+ // extra inset highlight, `inset 0 2px 1px -1px var(--box-primary)`.
78
+ //
79
+ // TASK 33 — this is now the real token, not a substitute. The designer's
80
+ // 4ec82cd ("jeden neutrální highlight pro tiles i menu") promoted
81
+ // --box-primary from a per-surface local custom property to ONE :root
82
+ // declaration, `--box-primary: hsl(0, 0%, 50%)` (jelinek.css:135), and
83
+ // deleted the local `--box-primary: var(--JELINEK-BLACK)` this rule's
84
+ // shared surface block used to carry. So the generator does emit it now
85
+ // (it is a PASSTHROUGH entry, see scripts/token-map.js for why it is not
86
+ // a Tailwind theme token) and it is referenced by name.
87
+ //
88
+ // The previous stand-in, var(--color-jelinek-black), was correct against
89
+ // the OLD guide and is wrong against this one: --JELINEK-BLACK inverts to
90
+ // hsl(0,0%,95%) in dark mode, so it would paint a near-white hairline
91
+ // where the guide now asks for a flat 50% grey. The css-lock gate caught
92
+ // the source rule moving; this is the component half of that.
93
+ 'dark:shadow-[var(--shadow-resting),inset_0_2px_1px_-1px_var(--box-primary)] ' +
94
+ 'dark:hover:shadow-[var(--shadow-interactive),inset_0_2px_1px_-1px_var(--box-primary)]';
95
+
96
+ // Only the linked form gets the hand cursor, and only because a tile is a
97
+ // whole-surface click target: the hover lift already promises "this does
98
+ // something", and a promise the cursor doesn't back up reads as a broken
99
+ // card. Every browser's UA sheet already gives `a[href]` cursor:pointer, so
100
+ // this is belt-and-braces against a host page (or an extension) that resets
101
+ // it — Tailwind's own preflight does exactly that to `button`, which is why
102
+ // Button.svelte carries a cursor-pointer too. Deliberately NOT on the `div`
103
+ // branch: a tile without `href` is inert, and a hand cursor over something
104
+ // that cannot be clicked is worse than no affordance at all. The guide's
105
+ // .tile (jelinek.css:917-928) declares no cursor of its own, so this is a
106
+ // kit-only addition, not a reproduction — the css-lock gate watches the
107
+ // guide's rule text and is unaffected.
108
+ const classes = $derived(cn(BASE, href && 'cursor-pointer', active && ACTIVE[color], className));
109
+ </script>
110
+
111
+ {#if href}
112
+ <a {...rest} {href} class={classes}>{@render children()}</a>
113
+ {:else}
114
+ <div {...rest} class={classes}>{@render children()}</div>
115
+ {/if}
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAnchorAttributes, HTMLAttributes } from 'svelte/elements';
3
+ type Color = 'brown' | 'magenta';
4
+ interface Props {
5
+ href?: string;
6
+ active?: boolean;
7
+ color?: Color;
8
+ class?: string;
9
+ children: Snippet;
10
+ }
11
+ type $$ComponentProps = Props & Omit<HTMLAnchorAttributes & HTMLAttributes<HTMLDivElement>, 'href'>;
12
+ declare const Tile: import("svelte").Component<$$ComponentProps, {}, "">;
13
+ type Tile = ReturnType<typeof Tile>;
14
+ export default Tile;
@@ -0,0 +1,199 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../utils/cn.js';
5
+
6
+ interface Props {
7
+ /**
8
+ * Accessible names for the two scroll arrows.
9
+ *
10
+ * DELIBERATELY NOT the guide's strings. assets/js/jelinek.js:502-503
11
+ * labels every scroller's arrows "Posunout na předchozí/další položky",
12
+ * because one `arrow()` helper builds them for `.tabs`,
13
+ * `.logo-tool__bgtabs` and `.tile-scroller` alike (jelinek.js:475). Put a
14
+ * Tabs and a TileScroller on one page — /ui/komponenty does exactly that
15
+ * — and a screen-reader user hears four buttons with two names between
16
+ * them, with nothing to say which row moves. Naming the thing that
17
+ * actually moves is worth the divergence; a caller who wants the guide's
18
+ * wording back can pass it.
19
+ */
20
+ prevLabel?: string;
21
+ nextLabel?: string;
22
+ class?: string;
23
+ children: Snippet;
24
+ }
25
+
26
+ let {
27
+ prevLabel = 'Posunout dlaždice zpět',
28
+ nextLabel = 'Posunout dlaždice dál',
29
+ class: className,
30
+ children,
31
+ ...rest
32
+ }: Props & HTMLAttributes<HTMLDivElement> = $props();
33
+
34
+ // ─── WHY THIS IS A COMPONENT AND NOT A `class` ON Grid ──────────────────
35
+ //
36
+ // jelinek.css:930-944 (`.tile-scroller`) is a full sibling of `.grid`: a
37
+ // one-line row that scrolls sideways instead of wrapping, for the case where
38
+ // a listing is a *rozcestník* (subcategories, recommended products) rather
39
+ // than the complete offer. The guide documents it as its own component in
40
+ // ui-old/komponenty.html#posuvne-dlazdice, and Task 35 brought that section
41
+ // into /ui/komponenty — which is what this exists to render.
42
+ //
43
+ // It is deliberately NOT a Grid variant. Grid's whole contract is "wrap into
44
+ // as many rows as it takes"; this one's is "never wrap, and let the last
45
+ // child be half-visible so the reader can see the row continues". Those are
46
+ // opposite answers to the same question, and a `scroll` prop on Grid would
47
+ // make every Grid caller carry the scroll machinery below.
48
+ //
49
+ // ROW — jelinek.css:930-940, one to one. gap-6 is var(--space-3) = 24px
50
+ // (theme.css pins --spacing to a literal 4px, so 6 × 4 = 24 exactly; see
51
+ // Tabs.svelte's note on why that pin matters). `scroll-snap-type: x
52
+ // proximity`, the hidden scrollbar and `scroll-behavior: smooth` have no
53
+ // Tailwind shorthand in this setup and stay arbitrary properties.
54
+ //
55
+ // THE PADDING/MARGIN PAIR IS LEVEL WITH THE SHADOWS, and the guide's own
56
+ // comment (jelinek.css:934-936) says why: a scroll container clips its
57
+ // content, so the tiles' shadow needs room — 12px each side, 24px below
58
+ // (how far the hover shadow reaches) and 4px above (the tile lifts by 2px).
59
+ // The negative side margins then cancel the horizontal reserve so the row
60
+ // still lines up with the surrounding text. Change one number without the
61
+ // other and either the shadow is sliced off or the row sits inset.
62
+ //
63
+ // `scroll-padding-inline: 12px` (jelinek.css:938) is the fix for what that
64
+ // pair breaks: without it, snapping ignores the 12px reserve and parks every
65
+ // tile 12px to the left of where the row's content actually starts.
66
+ const ROW =
67
+ 'flex flex-nowrap gap-6 overflow-x-auto [scroll-behavior:smooth] ' +
68
+ '[scroll-snap-type:x_proximity] [scrollbar-width:none] [-ms-overflow-style:none] ' +
69
+ '[&::-webkit-scrollbar]:hidden ' +
70
+ 'pt-1 pr-3 pb-6 pl-3 -mt-1 -mr-3 -ml-3 [scroll-padding-inline:12px] ' +
71
+ // jelinek.css:941-944 — how many tiles are visible at each breakpoint.
72
+ // Every basis is deliberately short of a whole division of the row (80,
73
+ // not 100; 46, not 50; 31, not 33.3; 23, not 25) so the NEXT tile is
74
+ // always partly on screen. That sliver is the affordance; the arrows are
75
+ // the second one, for people who do not read slivers.
76
+ '[&>*]:flex-[0_0_80%] [&>*]:[scroll-snap-align:start] ' +
77
+ 'min-[640px]:[&>*]:flex-[0_0_46%] min-[1024px]:[&>*]:flex-[0_0_31%] ' +
78
+ 'min-[1440px]:[&>*]:flex-[0_0_23%]';
79
+
80
+ // WRAPPER — jelinek.css:948 (`.tabs-scroll--below`) reserves 44px under the
81
+ // row for the arrow pair.
82
+ const WRAP = 'relative min-w-0 pb-11';
83
+
84
+ // ARROWS — jelinek.css:949-956. The `--below` variant differs from Tabs' in
85
+ // three ways, all of them deliberate in the guide: they sit UNDER the row
86
+ // rather than over its edges, they are 34px rather than 30, and at the end
87
+ // of the row they only DIM (opacity .35, pointer-events: none) instead of
88
+ // disappearing. The guide's comment gives the reason for the third —
89
+ // "aby dvojice šipek neposkakovala", so the pair does not jump about as you
90
+ // scroll. It also means neither button ever unmounts, so this component
91
+ // needs none of Tabs' focus hand-off: a keyboard user who exhausts one
92
+ // direction still has both buttons under their finger.
93
+ //
94
+ // Colours, radius, shadow and the transition pair are Tabs' ARROW verbatim
95
+ // (jelinek.css:858-866 + :872-873) — one shared rule in the guide, one
96
+ // shared appearance here.
97
+ const ARROW =
98
+ 'absolute bottom-0 flex h-[34px] w-[34px] items-center justify-center ' +
99
+ 'rounded-pill border-0 p-0 bg-surface text-fg-muted1 shadow-resting cursor-pointer ' +
100
+ 'transition-[background-color,color] duration-[var(--dur-base)] ease-[var(--ease)] ' +
101
+ 'hover:bg-jelinek-black hover:text-on-jelinek-black ' +
102
+ 'disabled:opacity-35 disabled:pointer-events-none disabled:cursor-default';
103
+
104
+ // State comes from the element, never from a breakpoint — a three-tile row
105
+ // on a wide screen does not overflow and correctly shows no arrows. Both
106
+ // start at 0 so the server-rendered HTML has no buttons; hydration adds them
107
+ // only if the row really does overflow. Slack of 2px is the guide's own
108
+ // (jelinek.js:506-508), so sub-pixel layout never leaves an arrow lit that
109
+ // cannot actually move.
110
+ let scroller = $state<HTMLElement | null>(null);
111
+ let scrollLeft = $state(0);
112
+ let scrollMax = $state(0);
113
+ const overflowing = $derived(scrollMax > 2);
114
+ const atStart = $derived(scrollLeft <= 2);
115
+ const atEnd = $derived(scrollLeft >= scrollMax - 2);
116
+
117
+ $effect(() => {
118
+ const el = scroller;
119
+ if (!el) return;
120
+ function measure() {
121
+ if (!el) return;
122
+ scrollLeft = el.scrollLeft;
123
+ scrollMax = el.scrollWidth - el.clientWidth;
124
+ }
125
+ measure();
126
+ el.addEventListener('scroll', measure, { passive: true });
127
+ const ro = new ResizeObserver(measure);
128
+ ro.observe(el);
129
+ return () => {
130
+ el.removeEventListener('scroll', measure);
131
+ ro.disconnect();
132
+ };
133
+ });
134
+
135
+ // jelinek.js:493-497 — 80% of the visible width per press, smooth. That is
136
+ // the same 80% as the mobile flex-basis by coincidence of the design, not by
137
+ // derivation: one press advances roughly one tile on a phone and roughly
138
+ // three on a wide screen, because the step is a share of the VIEWPORT, not
139
+ // of the tile.
140
+ function nudge(dir: 'prev' | 'next') {
141
+ const el = scroller;
142
+ if (!el) return;
143
+ const step = Math.round(el.clientWidth * 0.8) * (dir === 'prev' ? -1 : 1);
144
+ el.scrollBy({ left: step, behavior: 'smooth' });
145
+ }
146
+
147
+ // jelinek.js:459-463 (`chevron()`), byte for byte — see Tabs.svelte.
148
+ const CHEVRON = { prev: 'M15 6l-6 6 6 6', next: 'M9 6l6 6-6 6' };
149
+ </script>
150
+
151
+ <div class={WRAP}>
152
+ <div bind:this={scroller} {...rest} class={cn(ROW, className)}>
153
+ {@render children()}
154
+ </div>
155
+ {#if overflowing}
156
+ <button
157
+ type="button"
158
+ class={cn(ARROW, 'left-[calc(50%-40px)]')}
159
+ aria-label={prevLabel}
160
+ disabled={atStart}
161
+ onclick={() => nudge('prev')}
162
+ >
163
+ <svg
164
+ width="16"
165
+ height="16"
166
+ viewBox="0 0 24 24"
167
+ fill="none"
168
+ stroke="currentColor"
169
+ stroke-width="2.5"
170
+ stroke-linecap="round"
171
+ stroke-linejoin="round"
172
+ aria-hidden="true"
173
+ >
174
+ <path d={CHEVRON.prev} />
175
+ </svg>
176
+ </button>
177
+ <button
178
+ type="button"
179
+ class={cn(ARROW, 'right-[calc(50%-40px)]')}
180
+ aria-label={nextLabel}
181
+ disabled={atEnd}
182
+ onclick={() => nudge('next')}
183
+ >
184
+ <svg
185
+ width="16"
186
+ height="16"
187
+ viewBox="0 0 24 24"
188
+ fill="none"
189
+ stroke="currentColor"
190
+ stroke-width="2.5"
191
+ stroke-linecap="round"
192
+ stroke-linejoin="round"
193
+ aria-hidden="true"
194
+ >
195
+ <path d={CHEVRON.next} />
196
+ </svg>
197
+ </button>
198
+ {/if}
199
+ </div>
@@ -0,0 +1,25 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ interface Props {
4
+ /**
5
+ * Accessible names for the two scroll arrows.
6
+ *
7
+ * DELIBERATELY NOT the guide's strings. assets/js/jelinek.js:502-503
8
+ * labels every scroller's arrows "Posunout na předchozí/další položky",
9
+ * because one `arrow()` helper builds them for `.tabs`,
10
+ * `.logo-tool__bgtabs` and `.tile-scroller` alike (jelinek.js:475). Put a
11
+ * Tabs and a TileScroller on one page — /ui/komponenty does exactly that
12
+ * — and a screen-reader user hears four buttons with two names between
13
+ * them, with nothing to say which row moves. Naming the thing that
14
+ * actually moves is worth the divergence; a caller who wants the guide's
15
+ * wording back can pass it.
16
+ */
17
+ prevLabel?: string;
18
+ nextLabel?: string;
19
+ class?: string;
20
+ children: Snippet;
21
+ }
22
+ type $$ComponentProps = Props & HTMLAttributes<HTMLDivElement>;
23
+ declare const TileScroller: import("svelte").Component<$$ComponentProps, {}, "">;
24
+ type TileScroller = ReturnType<typeof TileScroller>;
25
+ export default TileScroller;
@@ -0,0 +1 @@
1
+ export declare const CONTAINER_CONTEXT: unique symbol;
@@ -0,0 +1,6 @@
1
+ // Marker context: "content rendered here already sits inside a `Container`
2
+ // (jelinek.css:287's `.container` — mx-auto/max-w-page/px-6)." No payload
3
+ // beyond presence is needed — unlike TABS_CONTEXT/RADIO_CONTEXT, which carry
4
+ // live state a child reads/writes, this is a one-way "is an ancestor already
5
+ // doing this job" signal, checked once via `hasContext()` (see PageHero.svelte).
6
+ export const CONTAINER_CONTEXT = Symbol('jelinek-container');
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The JELÍNEK deer-antler mark's SVG path data (the `d` attribute inside a
3
+ * `0 0 400 400` viewBox), verified byte-identical across every place the
4
+ * guide draws it: partials/header.html:4, all seven `.content-logo__svg`
5
+ * instances in ui/logo.html, and the copy SiteHeader.svelte already carried
6
+ * inline. Extracted here (Task 23, ContentLogo) so SiteHeader.svelte and
7
+ * ContentLogo.svelte share one copy of this ~490-character string instead
8
+ * of two that could silently drift apart — the surrounding markup around
9
+ * the path differs between the two components (SiteHeader's <rect> has no
10
+ * corner radius and re-themes via fill-jelinek-black/-white utility
11
+ * classes; ContentLogo's <rect> is a literal fill="#000" rounded square,
12
+ * rx/ry 25, jelinek.css:743-757, and the path itself is a literal
13
+ * fill="currentColor" so only the antlers — not the square behind them —
14
+ * follow the content division), only the path data itself is identical.
15
+ */
16
+ export declare const DEER_MARK_PATH = "M216.7,187.9h26.5c1,0,2,0,3,0,12.6,0,26.9.1,36.7-9.8,6.8-6.9,10.1-17.4,10.1-32h-12.7c0,10.8-2.1,18.5-6.4,22.8-6.1,6.1-17,6.1-27.7,6-1,0-2.1,0-3.1,0h-13.7v-33.5h-12.7v33.5h-23.2l-55-31v-48.2h-12.7v41l-9.1-5.1h-.3c-.5-.4-53.6-27.6-54.2-69.3l-12.7.2c.7,49,57.1,78.5,61.2,80.5l56.5,31.8h-41.4v6.5c0,12.5,5,19.7,11.5,25.4,6.5,5.7,22.9,5.7,22.9,5.7h19.3v-13h-22.9c-9.6,0-15.4-3.9-17.4-11.7h51l79.9,42.3v27.2l-32.6-12.5-2.4-.5-99,53.6v13.7l2.6-.3,99.6-53.6,34,13.2,10.4-4.7v-39.9l-3.3-5.7-63-32.8Z";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The JELÍNEK deer-antler mark's SVG path data (the `d` attribute inside a
3
+ * `0 0 400 400` viewBox), verified byte-identical across every place the
4
+ * guide draws it: partials/header.html:4, all seven `.content-logo__svg`
5
+ * instances in ui/logo.html, and the copy SiteHeader.svelte already carried
6
+ * inline. Extracted here (Task 23, ContentLogo) so SiteHeader.svelte and
7
+ * ContentLogo.svelte share one copy of this ~490-character string instead
8
+ * of two that could silently drift apart — the surrounding markup around
9
+ * the path differs between the two components (SiteHeader's <rect> has no
10
+ * corner radius and re-themes via fill-jelinek-black/-white utility
11
+ * classes; ContentLogo's <rect> is a literal fill="#000" rounded square,
12
+ * rx/ry 25, jelinek.css:743-757, and the path itself is a literal
13
+ * fill="currentColor" so only the antlers — not the square behind them —
14
+ * follow the content division), only the path data itself is identical.
15
+ */
16
+ export const DEER_MARK_PATH = 'M216.7,187.9h26.5c1,0,2,0,3,0,12.6,0,26.9.1,36.7-9.8,6.8-6.9,10.1-17.4,10.1-32h-12.7c0,10.8-2.1,18.5-6.4,22.8-6.1,6.1-17,6.1-27.7,6-1,0-2.1,0-3.1,0h-13.7v-33.5h-12.7v33.5h-23.2l-55-31v-48.2h-12.7v41l-9.1-5.1h-.3c-.5-.4-53.6-27.6-54.2-69.3l-12.7.2c.7,49,57.1,78.5,61.2,80.5l56.5,31.8h-41.4v6.5c0,12.5,5,19.7,11.5,25.4,6.5,5.7,22.9,5.7,22.9,5.7h19.3v-13h-22.9c-9.6,0-15.4-3.9-17.4-11.7h51l79.9,42.3v27.2l-32.6-12.5-2.4-.5-99,53.6v13.7l2.6-.3,99.6-53.6,34,13.2,10.4-4.7v-39.9l-3.3-5.7-63-32.8Z';
@@ -0,0 +1,25 @@
1
+ export type NavItem = {
2
+ href: string;
3
+ label: string;
4
+ /**
5
+ * How `active` is compared against this item's `href`.
6
+ *
7
+ * `'exact'` (the default) is right for a chapter link: only that page lights
8
+ * it up. `'prefix'` is for a SECTION link — the guide's own header marks
9
+ * "Brand guide" and "UI guide" active on every page inside them, not just on
10
+ * the section's index (partials/header.html:8-10 does it with the SSI `$nav`
11
+ * variable, which each page sets to `uvod`/`brand`/`ui`). Without this a
12
+ * top-level section link is lit on exactly one URL and dead on the twenty
13
+ * pages the reader actually gets there from.
14
+ *
15
+ * A `'prefix'` item whose href is `/` would match everything, so the root is
16
+ * special-cased to an exact compare — see isActive() in SiteHeader.
17
+ */
18
+ match?: 'exact' | 'prefix';
19
+ };
20
+ /**
21
+ * Does `pathname` count as being on `item`? Exported because SiteHeader renders
22
+ * the same list twice (the ≥640px row and the phone panel) and ChapterNav takes
23
+ * the same shape.
24
+ */
25
+ export declare function isActive(item: NavItem, pathname: string | undefined): boolean;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Does `pathname` count as being on `item`? Exported because SiteHeader renders
3
+ * the same list twice (the ≥640px row and the phone panel) and ChapterNav takes
4
+ * the same shape.
5
+ */
6
+ export function isActive(item, pathname) {
7
+ if (pathname === undefined)
8
+ return false;
9
+ if (item.match !== 'prefix')
10
+ return item.href === pathname;
11
+ // A bare "/" prefix would match every path, which is never what a section
12
+ // link means. Compare exactly instead.
13
+ const base = item.href.replace(/\/$/, '');
14
+ if (base === '')
15
+ return pathname === '/' || pathname === '';
16
+ return pathname === base || pathname.startsWith(`${base}/`);
17
+ }
@@ -0,0 +1,6 @@
1
+ export declare const RADIO_CONTEXT: unique symbol;
2
+ export type RadioContext = {
3
+ name: string;
4
+ current: () => string;
5
+ select: (value: string) => void;
6
+ };
@@ -0,0 +1 @@
1
+ export const RADIO_CONTEXT = Symbol('jelinek-radio-group');
@@ -0,0 +1,5 @@
1
+ export declare const TABS_CONTEXT: unique symbol;
2
+ export type TabsContext = {
3
+ current: () => string;
4
+ select: (value: string) => void;
5
+ };
@@ -0,0 +1 @@
1
+ export const TABS_CONTEXT = Symbol('jelinek-tabs');
@@ -0,0 +1,37 @@
1
+ export { cn } from './utils/cn.js';
2
+ export { createChapterNavDock } from './utils/chapter-nav-dock.svelte.js';
3
+ export { default as Alert } from './components/Alert.svelte';
4
+ export { default as Button } from './components/Button.svelte';
5
+ export { default as Card } from './components/Card.svelte';
6
+ export { default as ChapterNav } from './components/ChapterNav.svelte';
7
+ export { default as Checkbox } from './components/Checkbox.svelte';
8
+ export { default as CodeCopy } from './components/CodeCopy.svelte';
9
+ export { CONTAINER_CONTEXT } from './components/container-context.js';
10
+ export { default as Container } from './components/Container.svelte';
11
+ export { default as ContentLogo } from './components/ContentLogo.svelte';
12
+ export { default as Demo } from './components/Demo.svelte';
13
+ export { default as Eyebrow } from './components/Eyebrow.svelte';
14
+ export { default as Glass } from './components/Glass.svelte';
15
+ export { default as Grid } from './components/Grid.svelte';
16
+ export { default as Label } from './components/Label.svelte';
17
+ export { isActive, type NavItem } from './components/nav.js';
18
+ export { default as PageHero } from './components/PageHero.svelte';
19
+ export { default as Pager } from './components/Pager.svelte';
20
+ export { default as Panel } from './components/Panel.svelte';
21
+ export { default as ProductCard } from './components/ProductCard.svelte';
22
+ export { default as Radio } from './components/Radio.svelte';
23
+ export { RADIO_CONTEXT, type RadioContext } from './components/radio-context.js';
24
+ export { default as RadioGroup } from './components/RadioGroup.svelte';
25
+ export { default as Select } from './components/Select.svelte';
26
+ export { default as SiteFooter } from './components/SiteFooter.svelte';
27
+ export { default as SiteHeader } from './components/SiteHeader.svelte';
28
+ export { default as Slider } from './components/Slider.svelte';
29
+ export { default as Swatch } from './components/Swatch.svelte';
30
+ export { default as Tab } from './components/Tab.svelte';
31
+ export { default as Tabs } from './components/Tabs.svelte';
32
+ export { TABS_CONTEXT, type TabsContext } from './components/tabs-context.js';
33
+ export { default as Tag } from './components/Tag.svelte';
34
+ export { default as TextField } from './components/TextField.svelte';
35
+ export { default as ThemeToggle } from './components/ThemeToggle.svelte';
36
+ export { default as Tile } from './components/Tile.svelte';
37
+ export { default as TileScroller } from './components/TileScroller.svelte';
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ export { cn } from './utils/cn.js';
2
+ export { createChapterNavDock } from './utils/chapter-nav-dock.svelte.js';
3
+ export { default as Alert } from './components/Alert.svelte';
4
+ export { default as Button } from './components/Button.svelte';
5
+ export { default as Card } from './components/Card.svelte';
6
+ export { default as ChapterNav } from './components/ChapterNav.svelte';
7
+ export { default as Checkbox } from './components/Checkbox.svelte';
8
+ export { default as CodeCopy } from './components/CodeCopy.svelte';
9
+ export { CONTAINER_CONTEXT } from './components/container-context.js';
10
+ export { default as Container } from './components/Container.svelte';
11
+ export { default as ContentLogo } from './components/ContentLogo.svelte';
12
+ export { default as Demo } from './components/Demo.svelte';
13
+ export { default as Eyebrow } from './components/Eyebrow.svelte';
14
+ export { default as Glass } from './components/Glass.svelte';
15
+ export { default as Grid } from './components/Grid.svelte';
16
+ export { default as Label } from './components/Label.svelte';
17
+ export { isActive } from './components/nav.js';
18
+ export { default as PageHero } from './components/PageHero.svelte';
19
+ export { default as Pager } from './components/Pager.svelte';
20
+ export { default as Panel } from './components/Panel.svelte';
21
+ export { default as ProductCard } from './components/ProductCard.svelte';
22
+ export { default as Radio } from './components/Radio.svelte';
23
+ export { RADIO_CONTEXT } from './components/radio-context.js';
24
+ export { default as RadioGroup } from './components/RadioGroup.svelte';
25
+ export { default as Select } from './components/Select.svelte';
26
+ export { default as SiteFooter } from './components/SiteFooter.svelte';
27
+ export { default as SiteHeader } from './components/SiteHeader.svelte';
28
+ export { default as Slider } from './components/Slider.svelte';
29
+ export { default as Swatch } from './components/Swatch.svelte';
30
+ export { default as Tab } from './components/Tab.svelte';
31
+ export { default as Tabs } from './components/Tabs.svelte';
32
+ export { TABS_CONTEXT } from './components/tabs-context.js';
33
+ export { default as Tag } from './components/Tag.svelte';
34
+ export { default as TextField } from './components/TextField.svelte';
35
+ export { default as ThemeToggle } from './components/ThemeToggle.svelte';
36
+ export { default as Tile } from './components/Tile.svelte';
37
+ export { default as TileScroller } from './components/TileScroller.svelte';