@jelinek/ui 0.9.0 → 0.9.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.
- package/dist/components/ChapterNav.svelte +1 -1
- package/dist/components/Checkbox.svelte +13 -15
- package/dist/components/Checkbox.svelte.d.ts +1 -0
- package/dist/components/ContentLogo.svelte +18 -13
- package/dist/components/ContentLogo.svelte.d.ts +6 -5
- package/dist/components/Grid.svelte +9 -5
- package/dist/components/Label.svelte +12 -1
- package/dist/components/Label.svelte.d.ts +8 -0
- package/dist/components/PageHero.svelte +6 -7
- package/dist/components/Pager.svelte +5 -2
- package/dist/components/PhotoTile.svelte +4 -2
- package/dist/components/ProductCard.svelte +66 -44
- package/dist/components/ProductCard.svelte.d.ts +17 -4
- package/dist/components/Radio.svelte +12 -8
- package/dist/components/Radio.svelte.d.ts +1 -0
- package/dist/components/Select.svelte +70 -12
- package/dist/components/Select.svelte.d.ts +11 -0
- package/dist/components/SiteFooter.svelte +19 -0
- package/dist/components/SiteFooter.svelte.d.ts +8 -0
- package/dist/components/SiteHeader.svelte +11 -9
- package/dist/components/Slider.svelte +6 -11
- package/dist/components/Switch.svelte +76 -0
- package/dist/components/Switch.svelte.d.ts +12 -0
- package/dist/components/TextField.svelte +61 -10
- package/dist/components/TextField.svelte.d.ts +13 -0
- package/dist/components/Textarea.svelte +92 -0
- package/dist/components/Textarea.svelte.d.ts +23 -0
- package/dist/components/Tile.svelte +12 -11
- package/dist/components/Tile.svelte.d.ts +8 -2
- package/dist/components/blocks/CmsButton.svelte +36 -0
- package/dist/components/blocks/CmsButton.svelte.d.ts +12 -0
- package/dist/components/blocks/CmsColumns.svelte +20 -0
- package/dist/components/blocks/CmsColumns.svelte.d.ts +9 -0
- package/dist/components/blocks/CmsCover.svelte +71 -0
- package/dist/components/blocks/CmsCover.svelte.d.ts +17 -0
- package/dist/components/blocks/CmsHeading.svelte +50 -0
- package/dist/components/blocks/CmsHeading.svelte.d.ts +14 -0
- package/dist/components/blocks/CmsImage.svelte +43 -0
- package/dist/components/blocks/CmsImage.svelte.d.ts +13 -0
- package/dist/components/blocks/CmsMediaText.svelte +64 -0
- package/dist/components/blocks/CmsMediaText.svelte.d.ts +16 -0
- package/dist/components/blocks/CmsText.svelte +53 -0
- package/dist/components/blocks/CmsText.svelte.d.ts +10 -0
- package/dist/components/commerce/Breadcrumbs.svelte +22 -5
- package/dist/components/commerce/CartDrawer.svelte +7 -4
- package/dist/components/commerce/CartLineItem.svelte +1 -1
- package/dist/components/commerce/CheckoutProgress.svelte +1 -1
- package/dist/components/commerce/ConfigSection.svelte +2 -2
- package/dist/components/commerce/DimensionSlider.svelte +1 -1
- package/dist/components/commerce/Drawer.svelte +38 -24
- package/dist/components/commerce/Drawer.svelte.d.ts +0 -2
- package/dist/components/commerce/EmptyState.svelte +37 -0
- package/dist/components/commerce/EmptyState.svelte.d.ts +13 -0
- package/dist/components/commerce/FilterChip.svelte +35 -0
- package/dist/components/commerce/FilterChip.svelte.d.ts +10 -0
- package/dist/components/commerce/FreeShippingBar.svelte +1 -1
- package/dist/components/commerce/Gallery.svelte +4 -2
- package/dist/components/commerce/ListingToolbar.svelte +62 -0
- package/dist/components/commerce/ListingToolbar.svelte.d.ts +19 -0
- package/dist/components/commerce/Modal.svelte +31 -21
- package/dist/components/commerce/Modal.svelte.d.ts +0 -2
- package/dist/components/commerce/OrderSummary.svelte +1 -1
- package/dist/components/commerce/Pagination.svelte +115 -0
- package/dist/components/commerce/Pagination.svelte.d.ts +14 -0
- package/dist/components/commerce/PriceDisplay.svelte +3 -3
- package/dist/components/commerce/ProductHeader.svelte +2 -2
- package/dist/components/commerce/QuantityStepper.svelte +1 -1
- package/dist/components/commerce/RatingStars.svelte +1 -1
- package/dist/components/commerce/SearchField.svelte +92 -0
- package/dist/components/commerce/SearchField.svelte.d.ts +15 -0
- package/dist/components/commerce/SideToggle.svelte +1 -1
- package/dist/components/commerce/Skeleton.svelte +4 -1
- package/dist/components/commerce/StickyBar.svelte +4 -4
- package/dist/components/commerce/StockBadge.svelte +2 -2
- package/dist/components/commerce/Toaster.svelte +9 -5
- package/dist/components/commerce/TrustBadges.svelte +1 -1
- package/dist/components/commerce/overlay.d.ts +14 -0
- package/dist/components/commerce/overlay.js +49 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/theme/base.css +22 -0
- package/dist/theme/extras.css +44 -0
- package/dist/theme/fonts.css +6 -42
- package/dist/theme/tokens.css +16 -9
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
3
|
+
import { cn } from '../../utils/cn.js';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
value?: string;
|
|
7
|
+
/** Popisek pro čtečky (pole nemá viditelný label). */
|
|
8
|
+
label?: string;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
/** Zavolá se při odeslání (Enter) s aktuálním dotazem. */
|
|
11
|
+
onsearch?: (query: string) => void;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
class?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
value = $bindable(''),
|
|
18
|
+
label = 'Hledat',
|
|
19
|
+
placeholder = 'Hledat…',
|
|
20
|
+
onsearch,
|
|
21
|
+
disabled = false,
|
|
22
|
+
class: className,
|
|
23
|
+
...rest
|
|
24
|
+
}: Props & Omit<HTMLInputAttributes, 'value'> = $props();
|
|
25
|
+
|
|
26
|
+
// Field chrome is TextField's BASE verbatim (border-fg-muted2, 11px/14px
|
|
27
|
+
// padding, 0.98rem, tokenised focus ring — see TextField.svelte for the
|
|
28
|
+
// full provenance notes), with left padding widened for the magnifier and
|
|
29
|
+
// right padding for the clear button. type="search" is NOT used: WebKit
|
|
30
|
+
// draws its own clear control there, which would double up with ours.
|
|
31
|
+
const FIELD =
|
|
32
|
+
'w-full rounded-button border border-fg-muted2 bg-surface py-[11px] pr-11 pl-11 ' +
|
|
33
|
+
'font-secondary font-light text-[0.98rem] text-fg placeholder:text-fg-muted2 ' +
|
|
34
|
+
'focus:outline-[length:var(--focus-width)] focus:outline-offset-1 ' +
|
|
35
|
+
'focus:outline-[var(--focus-color)] focus:border-[var(--focus-color)]';
|
|
36
|
+
const DISABLED =
|
|
37
|
+
'cursor-not-allowed border-border-subtle bg-surface-gray text-fg-muted2 ' +
|
|
38
|
+
'placeholder:text-fg-muted2';
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<!-- role="search" comes with the <search>/form pattern: submit = Enter, which
|
|
42
|
+
is how people actually search. The magnifier is decorative (the field's
|
|
43
|
+
accessible name carries the meaning), the clear button is a real button. -->
|
|
44
|
+
<form
|
|
45
|
+
role="search"
|
|
46
|
+
class={cn('relative', className)}
|
|
47
|
+
onsubmit={(e) => {
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
onsearch?.(value);
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
<svg
|
|
53
|
+
viewBox="0 0 24 24"
|
|
54
|
+
class="pointer-events-none absolute top-1/2 left-3.5 size-5 -translate-y-1/2 text-fg-muted1"
|
|
55
|
+
fill="none"
|
|
56
|
+
stroke="currentColor"
|
|
57
|
+
stroke-width="2"
|
|
58
|
+
stroke-linecap="round"
|
|
59
|
+
aria-hidden="true"
|
|
60
|
+
>
|
|
61
|
+
<circle cx="11" cy="11" r="7" /><path d="m21 21-4.3-4.3" />
|
|
62
|
+
</svg>
|
|
63
|
+
<input
|
|
64
|
+
{...rest}
|
|
65
|
+
type="text"
|
|
66
|
+
aria-label={label}
|
|
67
|
+
{placeholder}
|
|
68
|
+
{disabled}
|
|
69
|
+
bind:value
|
|
70
|
+
class={cn(FIELD, disabled && DISABLED)}
|
|
71
|
+
/>
|
|
72
|
+
{#if value && !disabled}
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
aria-label="Vymazat hledání"
|
|
76
|
+
class="absolute top-1/2 right-2 inline-flex size-8 -translate-y-1/2 cursor-pointer
|
|
77
|
+
items-center justify-center rounded-button text-fg-muted1 transition-colors
|
|
78
|
+
duration-[var(--dur-base)] ease-[var(--ease)] hover:text-fg"
|
|
79
|
+
onclick={() => (value = '')}
|
|
80
|
+
>
|
|
81
|
+
<svg
|
|
82
|
+
viewBox="0 0 24 24"
|
|
83
|
+
class="size-4"
|
|
84
|
+
fill="none"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
stroke-width="2"
|
|
87
|
+
stroke-linecap="round"
|
|
88
|
+
aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg
|
|
89
|
+
>
|
|
90
|
+
</button>
|
|
91
|
+
{/if}
|
|
92
|
+
</form>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props {
|
|
3
|
+
value?: string;
|
|
4
|
+
/** Popisek pro čtečky (pole nemá viditelný label). */
|
|
5
|
+
label?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
/** Zavolá se při odeslání (Enter) s aktuálním dotazem. */
|
|
8
|
+
onsearch?: (query: string) => void;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
type $$ComponentProps = Props & Omit<HTMLInputAttributes, 'value'>;
|
|
13
|
+
declare const SearchField: import("svelte").Component<$$ComponentProps, {}, "value">;
|
|
14
|
+
type SearchField = ReturnType<typeof SearchField>;
|
|
15
|
+
export default SearchField;
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
<button
|
|
29
29
|
type="button"
|
|
30
|
-
class="rounded-card cursor-pointer border px-3 py-2.5 text-left transition-all duration-200 max-sm:px-2 max-sm:py-2 {active
|
|
30
|
+
class="rounded-card cursor-pointer border px-3 py-2.5 text-left font-secondary font-light transition-all duration-200 max-sm:px-2 max-sm:py-2 {active
|
|
31
31
|
? 'border-(--JELINEK-BROWN) bg-surface-gray shadow-resting'
|
|
32
32
|
: 'border-border-subtle bg-surface hover:border-(--text-muted2)'}"
|
|
33
33
|
aria-pressed={active}
|
|
@@ -7,4 +7,7 @@
|
|
|
7
7
|
let { class: className = '' }: Props = $props();
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
<!-- Shimmer místo pulzu (majitel, 14. 8. 2026) — projíždějící gradient,
|
|
11
|
+
definovaný v theme/extras.css (.skeleton-shimmer); tam je i klidová
|
|
12
|
+
varianta pro prefers-reduced-motion. -->
|
|
13
|
+
<div class="skeleton-shimmer rounded-card {className}" aria-hidden="true"></div>
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
let { visible, children }: Props = $props();
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
|
-
<!-- Glass strip under the kit's floating header card. z-40 keeps it
|
|
13
|
-
header (
|
|
12
|
+
<!-- Glass strip under the kit's floating header card. --z-bar (40) keeps it
|
|
13
|
+
BELOW the header (--z-header, 50) — any higher and the strip renders over the
|
|
14
14
|
card and its backdrop blur smears the whole top of the page. Top offset:
|
|
15
15
|
var(--header-h) from 640px up so the strip hangs under the fixed card;
|
|
16
16
|
top-0 on a phone, where the kit bar is absolute and has already scrolled
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
left the viewport). -->
|
|
19
19
|
<div
|
|
20
20
|
aria-hidden={!visible}
|
|
21
|
-
class="fixed inset-x-0 top-0 z-
|
|
21
|
+
class="fixed inset-x-0 top-0 z-(--z-bar) border-b border-(--glass-border) bg-(--glass-fill) backdrop-blur-[25px] backdrop-saturate-140 transition-transform duration-(--dur-base) min-[640px]:top-(--header-h)
|
|
22
22
|
{visible ? 'translate-y-0' : 'pointer-events-none -translate-y-[calc(100%+var(--header-h))]'}"
|
|
23
23
|
>
|
|
24
|
-
<div class="max-w-page mx-auto flex w-full items-center gap-4 px-6 py-3">
|
|
24
|
+
<div class="max-w-page mx-auto flex w-full items-center gap-4 px-6 py-3 font-secondary font-light">
|
|
25
25
|
{@render children()}
|
|
26
26
|
</div>
|
|
27
27
|
</div>
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
</script>
|
|
34
34
|
|
|
35
35
|
{#if compact}
|
|
36
|
-
<span class="inline-flex items-center gap-1.5 text-(length:--step-down1) font-medium {config.cls}">
|
|
36
|
+
<span class="inline-flex items-center gap-1.5 font-secondary text-(length:--step-down1) font-medium {config.cls}">
|
|
37
37
|
<span class="size-2 rounded-pill {config.dot}"></span>{text}
|
|
38
38
|
</span>
|
|
39
39
|
{:else}
|
|
40
40
|
<span
|
|
41
|
-
class="rounded-pill bg-surface-gray inline-flex items-center gap-2 px-3 py-1 text-(length:--step-down1) font-medium {config.cls}"
|
|
41
|
+
class="rounded-pill bg-surface-gray inline-flex items-center gap-2 px-3 py-1 font-secondary text-(length:--step-down1) font-medium {config.cls}"
|
|
42
42
|
>
|
|
43
43
|
<span class="size-2 rounded-pill {config.dot}"></span>{text}
|
|
44
44
|
</span>
|
|
@@ -17,16 +17,20 @@
|
|
|
17
17
|
onMount(() => toasts.subscribe((next) => (items = next)));
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
|
-
<!--
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
<!-- Škála vrstev (jelinek.css :root): hlavička --z-header (50), Drawer/Modal
|
|
21
|
+
--z-overlay (1200), toasty nade vším — --z-toast (1500; potvrzení
|
|
22
|
+
o přidání do košíku nesmí zmizet pod drawerem). role="status"
|
|
23
|
+
+ aria-live="polite": kontejner tu je trvale, takže čtečky ohlásí každý
|
|
24
|
+
toast, který do něj přibude — dřív byly hlášky pro čtečky němé (EAA). -->
|
|
23
25
|
<div
|
|
24
|
-
|
|
26
|
+
role="status"
|
|
27
|
+
aria-live="polite"
|
|
28
|
+
class="pointer-events-none fixed inset-x-0 bottom-6 z-(--z-toast) flex flex-col items-center gap-2 {className}"
|
|
25
29
|
>
|
|
26
30
|
{#each items as t (t.id)}
|
|
27
31
|
<div
|
|
28
32
|
transition:fly={{ y: 16, duration: 200 }}
|
|
29
|
-
class="rounded-pill text-fg-inverse shadow-interactive pointer-events-auto bg-(--bg-black) px-5 py-2.5 text-(length:--step-down1) font-medium"
|
|
33
|
+
class="rounded-pill text-fg-inverse shadow-interactive pointer-events-auto bg-(--bg-black) px-5 py-2.5 font-secondary text-(length:--step-down1) font-medium"
|
|
30
34
|
>
|
|
31
35
|
{t.message}
|
|
32
36
|
</div>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class={overlay ? 'absolute inset-x-3 bottom-3 flex flex-wrap gap-2' : 'flex flex-wrap gap-2'}>
|
|
18
18
|
{#each items as item (item.label)}
|
|
19
19
|
<span
|
|
20
|
-
class="rounded-pill flex items-center gap-1.5 bg-(--glass-fill) px-3 py-1.5 text-(length:--step-down2) font-medium backdrop-blur-[25px]"
|
|
20
|
+
class="rounded-pill flex items-center gap-1.5 bg-(--glass-fill) px-3 py-1.5 font-secondary text-(length:--step-down2) font-medium backdrop-blur-[25px]"
|
|
21
21
|
>
|
|
22
22
|
<item.icon class="size-3.5" />
|
|
23
23
|
{item.label}
|
|
@@ -10,3 +10,17 @@ export declare function portal(node: HTMLElement): {
|
|
|
10
10
|
};
|
|
11
11
|
/** Lock body scroll; returns the unlock function (for use inside $effect). */
|
|
12
12
|
export declare function lockScroll(): () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Past na fokus (zákonná přístupnost překryvů — EAA): Tab a Shift+Tab
|
|
15
|
+
* cyklí UVNITŘ containeru, do stránky pod overlayem se tabulátorem nedá
|
|
16
|
+
* vyjet. Myš ani Escape to nijak neomezuje. Vrací úklidovou funkci
|
|
17
|
+
* (pro $effect), stejná smlouva jako lockScroll().
|
|
18
|
+
*/
|
|
19
|
+
export declare function trapFocus(container: HTMLElement): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Zapamatuje si prvek zaostřený PŘED otevřením overlaye a vrátí funkci,
|
|
22
|
+
* která na něj fokus vrátí (pokud mezitím nezmizel ze stránky). Čtenář
|
|
23
|
+
* s klávesnicí tak po zavření pokračuje přesně tam, kde byl — typicky
|
|
24
|
+
* na tlačítku, kterým overlay otevřel.
|
|
25
|
+
*/
|
|
26
|
+
export declare function rememberFocus(): () => void;
|
|
@@ -18,3 +18,52 @@ export function lockScroll() {
|
|
|
18
18
|
document.body.style.overflow = prev;
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
// Co se v překryvu dá zaostřit tabulátorem. Bez filtru viditelnosti —
|
|
22
|
+
// otevřený overlay svůj obsah zobrazuje celý a jsdom (unit testy)
|
|
23
|
+
// offsetParent nezná.
|
|
24
|
+
const FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), ' +
|
|
25
|
+
'select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
26
|
+
/**
|
|
27
|
+
* Past na fokus (zákonná přístupnost překryvů — EAA): Tab a Shift+Tab
|
|
28
|
+
* cyklí UVNITŘ containeru, do stránky pod overlayem se tabulátorem nedá
|
|
29
|
+
* vyjet. Myš ani Escape to nijak neomezuje. Vrací úklidovou funkci
|
|
30
|
+
* (pro $effect), stejná smlouva jako lockScroll().
|
|
31
|
+
*/
|
|
32
|
+
export function trapFocus(container) {
|
|
33
|
+
const onKey = (e) => {
|
|
34
|
+
if (e.key !== 'Tab')
|
|
35
|
+
return;
|
|
36
|
+
const items = Array.from(container.querySelectorAll(FOCUSABLE));
|
|
37
|
+
if (items.length === 0) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
container.focus();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const first = items[0];
|
|
43
|
+
const last = items[items.length - 1];
|
|
44
|
+
const active = document.activeElement;
|
|
45
|
+
if (e.shiftKey && (active === first || active === container)) {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
last.focus();
|
|
48
|
+
}
|
|
49
|
+
else if (!e.shiftKey && active === last) {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
first.focus();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
container.addEventListener('keydown', onKey);
|
|
55
|
+
return () => container.removeEventListener('keydown', onKey);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Zapamatuje si prvek zaostřený PŘED otevřením overlaye a vrátí funkci,
|
|
59
|
+
* která na něj fokus vrátí (pokud mezitím nezmizel ze stránky). Čtenář
|
|
60
|
+
* s klávesnicí tak po zavření pokračuje přesně tam, kde byl — typicky
|
|
61
|
+
* na tlačítku, kterým overlay otevřel.
|
|
62
|
+
*/
|
|
63
|
+
export function rememberFocus() {
|
|
64
|
+
const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
65
|
+
return () => {
|
|
66
|
+
if (opener && document.contains(opener))
|
|
67
|
+
opener.focus();
|
|
68
|
+
};
|
|
69
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,13 @@ export { type CartLine } from './components/commerce/cart-types.js';
|
|
|
10
10
|
export { default as ChapterNav } from './components/ChapterNav.svelte';
|
|
11
11
|
export { default as Checkbox } from './components/Checkbox.svelte';
|
|
12
12
|
export { default as CheckoutProgress } from './components/commerce/CheckoutProgress.svelte';
|
|
13
|
+
export { default as CmsButton } from './components/blocks/CmsButton.svelte';
|
|
14
|
+
export { default as CmsColumns } from './components/blocks/CmsColumns.svelte';
|
|
15
|
+
export { default as CmsCover } from './components/blocks/CmsCover.svelte';
|
|
16
|
+
export { default as CmsHeading } from './components/blocks/CmsHeading.svelte';
|
|
17
|
+
export { default as CmsImage } from './components/blocks/CmsImage.svelte';
|
|
18
|
+
export { default as CmsMediaText } from './components/blocks/CmsMediaText.svelte';
|
|
19
|
+
export { default as CmsText } from './components/blocks/CmsText.svelte';
|
|
13
20
|
export { default as CodeCopy } from './components/CodeCopy.svelte';
|
|
14
21
|
export { default as ConfigSection } from './components/commerce/ConfigSection.svelte';
|
|
15
22
|
export { CONTAINER_CONTEXT } from './components/container-context.js';
|
|
@@ -18,19 +25,23 @@ export { default as ContentLogo } from './components/ContentLogo.svelte';
|
|
|
18
25
|
export { default as Demo } from './components/Demo.svelte';
|
|
19
26
|
export { default as DimensionSlider } from './components/commerce/DimensionSlider.svelte';
|
|
20
27
|
export { default as Drawer } from './components/commerce/Drawer.svelte';
|
|
28
|
+
export { default as EmptyState } from './components/commerce/EmptyState.svelte';
|
|
21
29
|
export { default as Eyebrow } from './components/Eyebrow.svelte';
|
|
30
|
+
export { default as FilterChip } from './components/commerce/FilterChip.svelte';
|
|
22
31
|
export { formatMoney, formatPrice } from './components/commerce/money.js';
|
|
23
32
|
export { default as FreeShippingBar } from './components/commerce/FreeShippingBar.svelte';
|
|
24
33
|
export { default as Gallery } from './components/commerce/Gallery.svelte';
|
|
25
34
|
export { default as Glass } from './components/Glass.svelte';
|
|
26
35
|
export { default as Grid } from './components/Grid.svelte';
|
|
27
36
|
export { default as Label } from './components/Label.svelte';
|
|
37
|
+
export { default as ListingToolbar } from './components/commerce/ListingToolbar.svelte';
|
|
28
38
|
export { default as Modal } from './components/commerce/Modal.svelte';
|
|
29
39
|
export { isActive, type NavItem, type NavGroup } from './components/nav.js';
|
|
30
40
|
export { default as OptionTile } from './components/OptionTile.svelte';
|
|
31
41
|
export { default as OrderSummary } from './components/commerce/OrderSummary.svelte';
|
|
32
42
|
export { default as PageHero } from './components/PageHero.svelte';
|
|
33
43
|
export { default as Pager } from './components/Pager.svelte';
|
|
44
|
+
export { default as Pagination } from './components/commerce/Pagination.svelte';
|
|
34
45
|
export { default as Panel } from './components/Panel.svelte';
|
|
35
46
|
export { default as PhotoTile } from './components/PhotoTile.svelte';
|
|
36
47
|
export { default as PriceDisplay } from './components/commerce/PriceDisplay.svelte';
|
|
@@ -43,6 +54,7 @@ export { default as Radio } from './components/Radio.svelte';
|
|
|
43
54
|
export { default as RatingStars } from './components/commerce/RatingStars.svelte';
|
|
44
55
|
export { RADIO_CONTEXT, type RadioContext } from './components/radio-context.js';
|
|
45
56
|
export { default as RadioGroup } from './components/RadioGroup.svelte';
|
|
57
|
+
export { default as SearchField } from './components/commerce/SearchField.svelte';
|
|
46
58
|
export { default as Select } from './components/Select.svelte';
|
|
47
59
|
export { portal } from './components/commerce/overlay.js';
|
|
48
60
|
export { default as SideToggle } from './components/commerce/SideToggle.svelte';
|
|
@@ -53,10 +65,12 @@ export { default as Slider } from './components/Slider.svelte';
|
|
|
53
65
|
export { default as StickyBar } from './components/commerce/StickyBar.svelte';
|
|
54
66
|
export { default as StockBadge } from './components/commerce/StockBadge.svelte';
|
|
55
67
|
export { default as Swatch } from './components/Swatch.svelte';
|
|
68
|
+
export { default as Switch } from './components/Switch.svelte';
|
|
56
69
|
export { default as Tab } from './components/Tab.svelte';
|
|
57
70
|
export { default as Tabs } from './components/Tabs.svelte';
|
|
58
71
|
export { TABS_CONTEXT, type TabsContext } from './components/tabs-context.js';
|
|
59
72
|
export { default as Tag } from './components/Tag.svelte';
|
|
73
|
+
export { default as Textarea } from './components/Textarea.svelte';
|
|
60
74
|
export { default as TextField } from './components/TextField.svelte';
|
|
61
75
|
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
62
76
|
export { default as Tile } from './components/Tile.svelte';
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,13 @@ export {} from './components/commerce/cart-types.js';
|
|
|
10
10
|
export { default as ChapterNav } from './components/ChapterNav.svelte';
|
|
11
11
|
export { default as Checkbox } from './components/Checkbox.svelte';
|
|
12
12
|
export { default as CheckoutProgress } from './components/commerce/CheckoutProgress.svelte';
|
|
13
|
+
export { default as CmsButton } from './components/blocks/CmsButton.svelte';
|
|
14
|
+
export { default as CmsColumns } from './components/blocks/CmsColumns.svelte';
|
|
15
|
+
export { default as CmsCover } from './components/blocks/CmsCover.svelte';
|
|
16
|
+
export { default as CmsHeading } from './components/blocks/CmsHeading.svelte';
|
|
17
|
+
export { default as CmsImage } from './components/blocks/CmsImage.svelte';
|
|
18
|
+
export { default as CmsMediaText } from './components/blocks/CmsMediaText.svelte';
|
|
19
|
+
export { default as CmsText } from './components/blocks/CmsText.svelte';
|
|
13
20
|
export { default as CodeCopy } from './components/CodeCopy.svelte';
|
|
14
21
|
export { default as ConfigSection } from './components/commerce/ConfigSection.svelte';
|
|
15
22
|
export { CONTAINER_CONTEXT } from './components/container-context.js';
|
|
@@ -18,19 +25,23 @@ export { default as ContentLogo } from './components/ContentLogo.svelte';
|
|
|
18
25
|
export { default as Demo } from './components/Demo.svelte';
|
|
19
26
|
export { default as DimensionSlider } from './components/commerce/DimensionSlider.svelte';
|
|
20
27
|
export { default as Drawer } from './components/commerce/Drawer.svelte';
|
|
28
|
+
export { default as EmptyState } from './components/commerce/EmptyState.svelte';
|
|
21
29
|
export { default as Eyebrow } from './components/Eyebrow.svelte';
|
|
30
|
+
export { default as FilterChip } from './components/commerce/FilterChip.svelte';
|
|
22
31
|
export { formatMoney, formatPrice } from './components/commerce/money.js';
|
|
23
32
|
export { default as FreeShippingBar } from './components/commerce/FreeShippingBar.svelte';
|
|
24
33
|
export { default as Gallery } from './components/commerce/Gallery.svelte';
|
|
25
34
|
export { default as Glass } from './components/Glass.svelte';
|
|
26
35
|
export { default as Grid } from './components/Grid.svelte';
|
|
27
36
|
export { default as Label } from './components/Label.svelte';
|
|
37
|
+
export { default as ListingToolbar } from './components/commerce/ListingToolbar.svelte';
|
|
28
38
|
export { default as Modal } from './components/commerce/Modal.svelte';
|
|
29
39
|
export { isActive } from './components/nav.js';
|
|
30
40
|
export { default as OptionTile } from './components/OptionTile.svelte';
|
|
31
41
|
export { default as OrderSummary } from './components/commerce/OrderSummary.svelte';
|
|
32
42
|
export { default as PageHero } from './components/PageHero.svelte';
|
|
33
43
|
export { default as Pager } from './components/Pager.svelte';
|
|
44
|
+
export { default as Pagination } from './components/commerce/Pagination.svelte';
|
|
34
45
|
export { default as Panel } from './components/Panel.svelte';
|
|
35
46
|
export { default as PhotoTile } from './components/PhotoTile.svelte';
|
|
36
47
|
export { default as PriceDisplay } from './components/commerce/PriceDisplay.svelte';
|
|
@@ -43,6 +54,7 @@ export { default as Radio } from './components/Radio.svelte';
|
|
|
43
54
|
export { default as RatingStars } from './components/commerce/RatingStars.svelte';
|
|
44
55
|
export { RADIO_CONTEXT } from './components/radio-context.js';
|
|
45
56
|
export { default as RadioGroup } from './components/RadioGroup.svelte';
|
|
57
|
+
export { default as SearchField } from './components/commerce/SearchField.svelte';
|
|
46
58
|
export { default as Select } from './components/Select.svelte';
|
|
47
59
|
export { portal } from './components/commerce/overlay.js';
|
|
48
60
|
export { default as SideToggle } from './components/commerce/SideToggle.svelte';
|
|
@@ -53,10 +65,12 @@ export { default as Slider } from './components/Slider.svelte';
|
|
|
53
65
|
export { default as StickyBar } from './components/commerce/StickyBar.svelte';
|
|
54
66
|
export { default as StockBadge } from './components/commerce/StockBadge.svelte';
|
|
55
67
|
export { default as Swatch } from './components/Swatch.svelte';
|
|
68
|
+
export { default as Switch } from './components/Switch.svelte';
|
|
56
69
|
export { default as Tab } from './components/Tab.svelte';
|
|
57
70
|
export { default as Tabs } from './components/Tabs.svelte';
|
|
58
71
|
export { TABS_CONTEXT } from './components/tabs-context.js';
|
|
59
72
|
export { default as Tag } from './components/Tag.svelte';
|
|
73
|
+
export { default as Textarea } from './components/Textarea.svelte';
|
|
60
74
|
export { default as TextField } from './components/TextField.svelte';
|
|
61
75
|
export { default as ThemeToggle } from './components/ThemeToggle.svelte';
|
|
62
76
|
export { default as Tile } from './components/Tile.svelte';
|
package/dist/theme/base.css
CHANGED
|
@@ -253,6 +253,25 @@
|
|
|
253
253
|
color var(--dur-slow) var(--ease);
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
/* KURZÍVA SE NEPOUŽÍVÁ NIKDY (brand → Typografie; majitel 14. 8. 2026) —
|
|
257
|
+
žádné písmo značky nemá skloněný řez a prohlížeč by si ho syntetizoval.
|
|
258
|
+
<em>/<i> se narovnává a zvýrazňuje tučně („ke zvýraznění slouží tučné
|
|
259
|
+
řezy“). Mirrors the identical rule in jelinek.css. */
|
|
260
|
+
em,
|
|
261
|
+
i {
|
|
262
|
+
font-style: normal;
|
|
263
|
+
font-weight: 700;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* <strong> pinned to Bold: the default `bolder` is RELATIVE — one step
|
|
267
|
+
up from Light (300) is Regular (400), a face outside the role system.
|
|
268
|
+
Contexts with their own rule (.card strong = Medium, Demo's
|
|
269
|
+
[&_strong]:font-medium utility) still win on specificity/layer. */
|
|
270
|
+
b,
|
|
271
|
+
strong {
|
|
272
|
+
font-weight: 700;
|
|
273
|
+
}
|
|
274
|
+
|
|
256
275
|
/* jelinek.css:316. The one flex child that should actually grow — header,
|
|
257
276
|
chapter-nav and footer keep their natural (content) height; whatever
|
|
258
277
|
space is left over goes to <main>, pushing the footer down to the
|
|
@@ -372,6 +391,9 @@
|
|
|
372
391
|
}
|
|
373
392
|
.serif {
|
|
374
393
|
font-family: var(--font-serif);
|
|
394
|
+
/* Archer only has Book (400) and Bold — a surrounding Light must not
|
|
395
|
+
be inherited into serif text. */
|
|
396
|
+
font-weight: 400;
|
|
375
397
|
}
|
|
376
398
|
.small {
|
|
377
399
|
font-size: var(--step-down1);
|
package/dist/theme/extras.css
CHANGED
|
@@ -19,3 +19,47 @@
|
|
|
19
19
|
[data-division='mattress'] {
|
|
20
20
|
--color-accent-text: var(--color-accent-text-mattress);
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
/* Jelen je jen hnědý, nebo bílý (brand → Znak, Užití s produktovými
|
|
24
|
+
barvami): divizní přetéma přemapovává --JELINEK-BROWN na magentu, ale pro
|
|
25
|
+
jelena je to zakázaný stav — pod divizí Zdravý spánek přechází KAŽDÉ
|
|
26
|
+
obsahové logo na bílou, divizní barvu jelena. Zrcadlí stejné pravidlo
|
|
27
|
+
v jelinek.css u .content-logo. */
|
|
28
|
+
[data-division='mattress'] [data-content-logo],
|
|
29
|
+
[data-theme='mattress'] [data-content-logo] {
|
|
30
|
+
color: var(--color-fg-inverse);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Skeleton shimmer (majitel, 14. 8. 2026): placeholder při načítání nese
|
|
34
|
+
projíždějící světlý gradient, jak je dnes zvykem — ne jen pulz. Barvy
|
|
35
|
+
jsou tokeny (klidová --bg-gray, projíždějící světlo --bg-white), takže
|
|
36
|
+
se v tmavém režimu překlopí samy. Smyčka 1,5 s je vlastní hodnota:
|
|
37
|
+
pohybové tokeny (--dur-*) popisují přechody stavů, ne nekonečné smyčky.
|
|
38
|
+
Kdo si v systému vypnul animace, dostane klidnou plochu — první kousek
|
|
39
|
+
prefers-reduced-motion v kitu (zásobník: Ohled na omezení pohybu). */
|
|
40
|
+
@keyframes skeleton-shimmer {
|
|
41
|
+
to {
|
|
42
|
+
transform: translateX(100%);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
.skeleton-shimmer {
|
|
46
|
+
position: relative;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
background: var(--color-surface-gray);
|
|
49
|
+
}
|
|
50
|
+
/* Světelný pás jede přes celou plochu jako vrstva nad ní (transform, ne
|
|
51
|
+
background-position) — na malém řádku i velké fotce je pohyb stejně
|
|
52
|
+
viditelný a nemá hluchá místa. */
|
|
53
|
+
.skeleton-shimmer::after {
|
|
54
|
+
content: '';
|
|
55
|
+
position: absolute;
|
|
56
|
+
inset: 0;
|
|
57
|
+
transform: translateX(-100%);
|
|
58
|
+
background: linear-gradient(90deg, transparent, var(--color-surface) 55%, transparent);
|
|
59
|
+
animation: skeleton-shimmer 1.5s ease-in-out infinite;
|
|
60
|
+
}
|
|
61
|
+
@media (prefers-reduced-motion: reduce) {
|
|
62
|
+
.skeleton-shimmer::after {
|
|
63
|
+
content: none;
|
|
64
|
+
}
|
|
65
|
+
}
|
package/dist/theme/fonts.css
CHANGED
|
@@ -21,13 +21,12 @@
|
|
|
21
21
|
|
|
22
22
|
Reconciled against assets/css/jelinek.css's @font-face block (the
|
|
23
23
|
authority for which faces exist): every face declared there is declared
|
|
24
|
-
here too, with the same family name, weight and filename.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
the
|
|
29
|
-
|
|
30
|
-
7cd378c). */
|
|
24
|
+
here too, with the same family name, weight and filename. Only the ROLE
|
|
25
|
+
faces are loaded (majitel, 21. 8. 2026): Walsheim Light/Medium/Bold,
|
|
26
|
+
Archer Book/Bold, Avenir Demi (logo subtitle). Regular, Black, Avenir
|
|
27
|
+
Regular/Bold and Archer Medium stay in assets/fonts/ for other projects,
|
|
28
|
+
but the web never declares them — a stray request falls back and the
|
|
29
|
+
font-faces e2e catches it. */
|
|
31
30
|
@font-face {
|
|
32
31
|
font-family: 'GT Walsheim Pro';
|
|
33
32
|
src: url('/assets/fonts/GT-Walsheim-Pro-Light.woff2') format('woff2');
|
|
@@ -35,13 +34,6 @@
|
|
|
35
34
|
font-style: normal;
|
|
36
35
|
font-display: block;
|
|
37
36
|
}
|
|
38
|
-
@font-face {
|
|
39
|
-
font-family: 'GT Walsheim Pro';
|
|
40
|
-
src: url('/assets/fonts/GT-Walsheim-Pro-Regular.woff2') format('woff2');
|
|
41
|
-
font-weight: 400;
|
|
42
|
-
font-style: normal;
|
|
43
|
-
font-display: block;
|
|
44
|
-
}
|
|
45
37
|
@font-face {
|
|
46
38
|
font-family: 'GT Walsheim Pro';
|
|
47
39
|
src: url('/assets/fonts/GT-Walsheim-Pro-Medium.woff2') format('woff2');
|
|
@@ -56,20 +48,6 @@
|
|
|
56
48
|
font-style: normal;
|
|
57
49
|
font-display: block;
|
|
58
50
|
}
|
|
59
|
-
@font-face {
|
|
60
|
-
font-family: 'GT Walsheim Pro';
|
|
61
|
-
src: url('/assets/fonts/GT-Walsheim-Pro-Black.woff2') format('woff2');
|
|
62
|
-
font-weight: 900;
|
|
63
|
-
font-style: normal;
|
|
64
|
-
font-display: block;
|
|
65
|
-
}
|
|
66
|
-
@font-face {
|
|
67
|
-
font-family: 'Avenir Next LT Pro';
|
|
68
|
-
src: url('/assets/fonts/AvenirNextLTPro-Regular.woff2') format('woff2');
|
|
69
|
-
font-weight: 400;
|
|
70
|
-
font-style: normal;
|
|
71
|
-
font-display: block;
|
|
72
|
-
}
|
|
73
51
|
@font-face {
|
|
74
52
|
font-family: 'Avenir Next LT Pro';
|
|
75
53
|
src: url('/assets/fonts/AvenirNextLTPro-Demi.woff2') format('woff2');
|
|
@@ -77,13 +55,6 @@
|
|
|
77
55
|
font-style: normal;
|
|
78
56
|
font-display: block;
|
|
79
57
|
}
|
|
80
|
-
@font-face {
|
|
81
|
-
font-family: 'Avenir Next LT Pro';
|
|
82
|
-
src: url('/assets/fonts/AvenirNextLTPro-Bold.woff2') format('woff2');
|
|
83
|
-
font-weight: 700;
|
|
84
|
-
font-style: normal;
|
|
85
|
-
font-display: block;
|
|
86
|
-
}
|
|
87
58
|
@font-face {
|
|
88
59
|
font-family: 'Archer';
|
|
89
60
|
src: url('/assets/fonts/Archer-Book.woff2') format('woff2');
|
|
@@ -91,13 +62,6 @@
|
|
|
91
62
|
font-style: normal;
|
|
92
63
|
font-display: block;
|
|
93
64
|
}
|
|
94
|
-
@font-face {
|
|
95
|
-
font-family: 'Archer';
|
|
96
|
-
src: url('/assets/fonts/Archer-Medium.woff2') format('woff2');
|
|
97
|
-
font-weight: 500;
|
|
98
|
-
font-style: normal;
|
|
99
|
-
font-display: block;
|
|
100
|
-
}
|
|
101
65
|
@font-face {
|
|
102
66
|
font-family: 'Archer';
|
|
103
67
|
src: url('/assets/fonts/Archer-Bold.woff2') format('woff2');
|
package/dist/theme/tokens.css
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
--ON-JELINEK-BLACK: hsl(0, 0%, 95%);
|
|
17
17
|
--bg-white: hsl(0, 0%, 100%);
|
|
18
18
|
--bg-gray: hsl(0, 0%, 95%);
|
|
19
|
-
--bg-brown: hsl(
|
|
20
|
-
--bg-magenta: hsl(324,
|
|
19
|
+
--bg-brown: hsl(27, 58%, 96.3%);
|
|
20
|
+
--bg-magenta: hsl(324, 85%, 92%);
|
|
21
21
|
--bg-black: hsl(0, 0%, 0%);
|
|
22
22
|
--border-subtle: hsl(0, 0%, 91%);
|
|
23
23
|
--text-black: hsl(0, 0%, 5%);
|
|
@@ -45,13 +45,20 @@
|
|
|
45
45
|
--glass-fill: hsl(0, 0%, 100%, 0.5);
|
|
46
46
|
--glass-border: hsl(0, 0%, 100%, 0.75);
|
|
47
47
|
--glass-filter: blur(25px) saturate(140%);
|
|
48
|
-
--
|
|
48
|
+
--overlay-scrim: hsl(0, 0%, 0%, 0.5);
|
|
49
|
+
--overlay-filter: blur(4px);
|
|
50
|
+
--z-bar: 40;
|
|
51
|
+
--z-chapter-nav: 49;
|
|
52
|
+
--z-header: 50;
|
|
53
|
+
--z-overlay: 1200;
|
|
54
|
+
--z-toast: 1500;
|
|
55
|
+
--focus-color: var(--JELINEK-BLACK);
|
|
49
56
|
--focus-width: 2px;
|
|
50
57
|
--focus-offset: 2px;
|
|
51
|
-
--font-primary: "GT Walsheim Pro", Arial, Helvetica, sans-serif;
|
|
58
|
+
--font-primary: "GT Walsheim Pro", "Arial Black", Arial, Helvetica, sans-serif;
|
|
52
59
|
--font-secondary: "GT Walsheim Pro", Arial, Helvetica, sans-serif;
|
|
53
|
-
--font-serif: "Archer", Georgia, "Times New Roman", serif;
|
|
54
|
-
--page-max:
|
|
60
|
+
--font-serif: "Archer", Baskerville, "Baskerville Old Face", Georgia, "Times New Roman", serif;
|
|
61
|
+
--page-max: 1480px;
|
|
55
62
|
--header-h: 70px;
|
|
56
63
|
--subnav-h: 58px;
|
|
57
64
|
--step0: 1rem;
|
|
@@ -82,8 +89,8 @@
|
|
|
82
89
|
.dark {
|
|
83
90
|
--bg-white: hsl(0, 0%, 5%);
|
|
84
91
|
--bg-gray: hsl(0, 0%, 15%);
|
|
85
|
-
--bg-brown: hsl(
|
|
86
|
-
--bg-magenta: hsl(324,
|
|
92
|
+
--bg-brown: hsl(27, 58%, 10%);
|
|
93
|
+
--bg-magenta: hsl(324, 85%, 10%);
|
|
87
94
|
--bg-black: hsl(0, 0%, 0%);
|
|
88
95
|
--text-black: hsl(0, 0%, 92%);
|
|
89
96
|
--text-muted1: hsl(0, 0%, 62%);
|
|
@@ -105,7 +112,7 @@
|
|
|
105
112
|
--sem-error-strong: hsl(5, 100%, 54%);
|
|
106
113
|
--glass-fill: hsl(0, 0%, 0%, 0.6);
|
|
107
114
|
--glass-border: hsl(0, 0%, 100%, 0.25);
|
|
108
|
-
--focus-color: var(--JELINEK-
|
|
115
|
+
--focus-color: var(--JELINEK-BLACK);
|
|
109
116
|
--border-subtle: hsl(0, 0%, 20%);
|
|
110
117
|
--border-highlight-white: hsl(0, 0%, 40%);
|
|
111
118
|
--shadow-interactive: 0px 4px 4px hsl(0, 0%, 0%, 0.063), 0px 12px 12px hsl(0, 0%, 0%, 0.188);
|