@krizaka/ui 3.41.0 → 3.42.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 (37) hide show
  1. package/dist/bird-plate.js +1 -1
  2. package/dist/{chunk-M4DBVG43.js → chunk-MHUUNC5W.js} +4 -3
  3. package/dist/chunk-MHUUNC5W.js.map +1 -0
  4. package/dist/{chunk-EZC54B5C.js → chunk-MIMOTE4W.js} +3 -3
  5. package/dist/{chunk-EZC54B5C.js.map → chunk-MIMOTE4W.js.map} +1 -1
  6. package/dist/{chunk-7JFHTPI3.js → chunk-P4TTKYC4.js} +8 -8
  7. package/dist/chunk-P4TTKYC4.js.map +1 -0
  8. package/dist/flock.d.ts +7 -1
  9. package/dist/flock.js +386 -50
  10. package/dist/flock.js.map +1 -1
  11. package/dist/mascot-quote.js +1 -1
  12. package/dist/mascot-state.js +1 -1
  13. package/dist/mascots.d.ts +3 -1
  14. package/dist/mascots.js +1 -1
  15. package/dist/nav-bar.js +1 -1
  16. package/dist/site-footer.d.ts +6 -4
  17. package/dist/site-footer.js +30 -6
  18. package/dist/site-footer.js.map +1 -1
  19. package/dist/sites.js +7 -7
  20. package/dist/sites.js.map +1 -1
  21. package/package.json +6 -6
  22. package/registry/examples/flock/scenes.d.ts +4 -0
  23. package/registry/examples/flock/scenes.js +28 -0
  24. package/registry/examples/flock/scenes.tsx +24 -0
  25. package/registry/examples/specimen-tag/product.js +1 -1
  26. package/registry/examples/specimen-tag/product.tsx +1 -1
  27. package/registry/flock.json +33 -5
  28. package/registry/index.json +8 -8
  29. package/registry/map.json +1 -1
  30. package/registry/mascots.json +15 -1
  31. package/registry/nav-bar.json +1 -1
  32. package/registry/rail-nav.json +1 -1
  33. package/registry/site-footer.json +16 -2
  34. package/registry/sites.json +1 -1
  35. package/registry/specimen-tag.json +2 -2
  36. package/dist/chunk-7JFHTPI3.js.map +0 -1
  37. package/dist/chunk-M4DBVG43.js.map +0 -1
package/dist/flock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/flock/flock.tsx"],"sourcesContent":["\"use client\";\n\n// The flock, alive: birds standing on a stage, each at ease in character (Mascot `life`), and the moments between\n// them — two birds glance at each other, the pigeon carries its parcel across, a bird looks up when you come near or tap\n// it. Transform and opacity only: CSS for each bird's own life, a timer for the moments (no frame loop), and nothing at\n// all when the flock is off screen, the tab is hidden or the person asked for less motion.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport type { MascotBird, MascotLook } from \"../mascots\";\nimport { Mascot } from \"../mascots\";\n\nexport interface FlockBird {\n /** Which bird. */\n bird: MascotBird;\n /** Where its feet are, across the stage: 0 to 100 (% of the stage's width). */\n x: number;\n /** Where its feet are, down the stage: 0 to 100 (% of the stage's height). */\n y: number;\n /** How wide it is: % of the stage's width. */\n size: number;\n}\n\nexport interface FlockMoments {\n /** Two neighbours look at each other now and then. Default `true`. */\n glance?: boolean;\n /** The pigeon, when the flock has one, carries its parcel across to another bird and comes back. Default `true`. */\n courier?: boolean;\n /** A bird looks up when the pointer comes near, and jumps a little when tapped. Default `true`. */\n react?: boolean;\n}\n\nexport type FlockProps = Omit<React.ComponentProps<\"div\">, \"children\"> &\n FlockMoments & {\n /** The birds on the stage. */\n birds: readonly FlockBird[];\n /** The stage's shape, width over height (default 16 / 9). It keeps its ratio at any width, so the birds keep their places. */\n ratio?: number;\n /** The birds' colours: the host's accent (`brand`, default) or the Krizaka story's (`own`). */\n tone?: \"brand\" | \"own\";\n /** The source of chance (default `Math.random`): give it a fixed one in a test. */\n random?: () => number;\n /** How lively the moments are: 1 is calm (default), 2 doubles how often neighbours glance and the pigeon delivers. */\n tempo?: number;\n /** A bird the page points at (a product the reader is on): it looks up and jumps once each time it changes. */\n active?: MascotBird | null;\n /** The birds greet the reader once as the flock first comes into view: each jumps in turn, left to right. */\n greet?: boolean;\n };\n\n// @fixed: the rhythm of the moments — how long a glance lasts, how often one happens, how long a delivery takes. A\n// choreography's pace, not a business parameter.\nconst GLANCE_HOLD_MS = [1500, 2400] as const;\nconst GLANCE_EVERY_MS = [4200, 9000] as const;\nconst COURIER_FIRST_MS = 9000;\nconst COURIER_EVERY_MS = [26000, 38000] as const;\nconst FLIGHT_MS = 2600;\nconst HAND_OVER_MS = 1300;\nconst LOOK_BACK_MS = 1600;\n\nconst between = (random: () => number, [lo, hi]: readonly [number, number], tempo = 1) => (lo + random() * (hi - lo)) / tempo;\nconst GREET_STEP_MS = 110;\nconst POKE_MS = 700;\n\n/** `true` while the page may move: no reduced-motion request, the tab visible. */\nfunction useMayMove(): boolean {\n const [may, setMay] = React.useState(false);\n React.useEffect(() => {\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const update = () => setMay(!query.matches && document.visibilityState !== \"hidden\");\n update();\n query.addEventListener(\"change\", update);\n document.addEventListener(\"visibilitychange\", update);\n return () => {\n query.removeEventListener(\"change\", update);\n document.removeEventListener(\"visibilitychange\", update);\n };\n }, []);\n return may;\n}\n\n/** `true` while the element is on screen. */\nfunction useOnScreen(ref: React.RefObject<Element | null>): boolean {\n const [on, setOn] = React.useState(false);\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(([entry]) => setOn(Boolean(entry?.isIntersecting)), { threshold: 0.1 });\n observer.observe(el);\n return () => observer.disconnect();\n }, [ref]);\n return on;\n}\n\n/**\n * The flock on its stage, alive. Decorative (`aria-hidden`): put the words beside it. Each bird idles in character; every\n * few seconds two neighbours glance at each other; every half minute the pigeon carries its parcel to another bird and\n * returns; a bird looks up when you come near. All of it pauses off screen and in a hidden tab, and the flock is still\n * under `prefers-reduced-motion`.\n */\nexport function Flock({ birds, ratio = 16 / 9, tone = \"brand\", glance = true, courier = true, react = true, random = Math.random, tempo = 1, active = null, greet = false, className, style, ...props }: FlockProps) {\n const stage = React.useRef<HTMLDivElement>(null);\n const bodies = React.useRef<(HTMLDivElement | null)[]>([]);\n const may = useMayMove();\n const onScreen = useOnScreen(stage);\n const running = may && onScreen;\n const [looks, setLooks] = React.useState<Record<number, MascotLook>>({});\n const [flying, setFlying] = React.useState<{ index: number; bank: number } | null>(null);\n const [poked, setPoked] = React.useState<Record<number, boolean>>({});\n\n // Left to right: a bird's neighbours are the birds beside it on the stage.\n const order = React.useMemo(() => birds.map((_, i) => i).sort((a, b) => birds[a]!.x - birds[b]!.x), [birds]);\n const look = (index: number, to: MascotLook) => setLooks((l) => (l[index] === to ? l : { ...l, [index]: to }));\n const rest = (...indexes: number[]) => setLooks((l) => Object.fromEntries(Object.entries(l).filter(([k]) => !indexes.includes(Number(k)))));\n\n // Glances: two neighbours turn towards each other, hold, and look away.\n React.useEffect(() => {\n if (!running || !glance || order.length < 2) return;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let back: ReturnType<typeof setTimeout> | undefined;\n const next = () => {\n timer = setTimeout(() => {\n const at = Math.floor(random() * (order.length - 1));\n const [a, b] = [order[at]!, order[at + 1]!];\n look(a, \"right\");\n look(b, \"left\");\n back = setTimeout(() => {\n rest(a, b);\n next();\n }, between(random, GLANCE_HOLD_MS));\n }, between(random, GLANCE_EVERY_MS, tempo));\n };\n next();\n return () => {\n clearTimeout(timer);\n clearTimeout(back);\n };\n }, [running, glance, order, random, tempo]);\n\n // The delivery: the pigeon takes its parcel across to the farthest bird, hands it over, and flies back.\n React.useEffect(() => {\n const pigeon = birds.findIndex((b) => b.bird === \"pigeon\");\n if (!running || !courier || pigeon < 0 || birds.length < 2) return;\n let alive = true;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let animation: Animation | undefined;\n const wait = (ms: number) => new Promise<void>((resolve) => (timer = setTimeout(resolve, ms)));\n const trip = async () => {\n const el = bodies.current[pigeon];\n const box = stage.current?.getBoundingClientRect();\n if (!el || !box || typeof el.animate !== \"function\") return;\n // The farthest bird from the pigeon, so the parcel crosses the whole stage.\n const from = birds[pigeon]!;\n const target = birds.reduce((far, b, i) => (i !== pigeon && Math.abs(b.x - from.x) > Math.abs(birds[far]!.x - from.x) ? i : far), pigeon === 0 ? 1 : 0);\n const to = birds[target]!;\n const side = to.x > from.x ? 1 : -1;\n // It lands beside the receiver, not on it.\n const dx = ((to.x - from.x) / 100) * box.width - side * (to.size / 100) * box.width * 0.55;\n const lift = (from.size / 100) * box.width * 0.35;\n const fly = async (fromX: number, toX: number) => {\n setFlying({ index: pigeon, bank: Math.sign(toX - fromX) });\n animation = el.animate(\n [\n { transform: `translate(${fromX}px, 0)`, easing: \"ease-out\" },\n { transform: `translate(${(fromX + toX) / 2}px, ${-lift}px)`, easing: \"ease-in\", offset: 0.5 },\n { transform: `translate(${toX}px, 0)` },\n ],\n { duration: FLIGHT_MS, fill: \"forwards\" },\n );\n await animation.finished.catch(() => undefined);\n setFlying(null);\n };\n look(target, side > 0 ? \"left\" : \"right\");\n await fly(0, dx);\n if (!alive) return;\n // The hand-over: the receiver looks at the pigeon, the pigeon hops on the doorstep.\n setPoked((p) => ({ ...p, [pigeon]: true }));\n await wait(HAND_OVER_MS);\n if (!alive) return;\n setPoked((p) => ({ ...p, [pigeon]: false }));\n look(target, \"up\");\n await fly(dx, 0);\n animation?.cancel();\n rest(target);\n };\n const schedule = (ms: number) => {\n timer = setTimeout(async () => {\n await trip();\n if (alive) schedule(between(random, COURIER_EVERY_MS, tempo));\n }, ms);\n };\n schedule(COURIER_FIRST_MS / tempo);\n return () => {\n alive = false;\n clearTimeout(timer);\n animation?.cancel();\n setFlying(null);\n };\n }, [running, courier, birds, random, tempo]);\n\n // The greeting: the first time the flock is on screen, each bird jumps in turn.\n const greeted = React.useRef(false);\n React.useEffect(() => {\n if (!running || !greet || greeted.current) return;\n greeted.current = true;\n const timers: ReturnType<typeof setTimeout>[] = [];\n order.forEach((index, n) => {\n timers.push(setTimeout(() => setPoked((p) => ({ ...p, [index]: true })), n * GREET_STEP_MS));\n timers.push(setTimeout(() => setPoked((p) => ({ ...p, [index]: false })), n * GREET_STEP_MS + POKE_MS));\n });\n return () => timers.forEach(clearTimeout);\n }, [running, greet, order]);\n\n // The bird the page points at looks up and jumps.\n React.useEffect(() => {\n const index = active ? birds.findIndex((b) => b.bird === active) : -1;\n if (!running || index < 0) return;\n const start = setTimeout(() => {\n look(index, \"up\");\n setPoked((p) => ({ ...p, [index]: true }));\n }, 0);\n const t = setTimeout(() => setPoked((p) => ({ ...p, [index]: false })), POKE_MS);\n return () => {\n clearTimeout(start);\n clearTimeout(t);\n setPoked((p) => ({ ...p, [index]: false }));\n rest(index);\n };\n }, [active, running, birds]);\n\n // A bird looks up when you come near, and jumps when you tap it.\n const hover = (index: number, event: React.PointerEvent) => {\n if (!running || !react || event.pointerType !== \"mouse\") return;\n look(index, \"up\");\n };\n const leave = (index: number) => {\n if (!react) return;\n rest(index);\n };\n const tap = (index: number) => {\n if (!running || !react) return;\n look(index, \"up\");\n setPoked((p) => ({ ...p, [index]: true }));\n setTimeout(() => {\n setPoked((p) => ({ ...p, [index]: false }));\n rest(index);\n }, LOOK_BACK_MS);\n };\n\n return (\n <div\n ref={stage}\n aria-hidden\n data-flock=\"\"\n data-running={running ? \"\" : undefined}\n className={cn(\"relative w-full\", className)}\n style={{ aspectRatio: String(ratio), containerType: \"inline-size\", ...style }}\n {...props}\n >\n {birds.map((b, i) => (\n <div\n key={`${b.bird}-${i}`}\n ref={(el) => {\n bodies.current[i] = el;\n }}\n data-flock-bird={b.bird}\n className=\"absolute touch-manipulation\"\n style={{ left: `${b.x - b.size / 2}%`, width: `${b.size}%`, top: `calc(${b.y}% - ${b.size * 0.9}cqw)`, aspectRatio: \"1\", pointerEvents: react ? \"auto\" : \"none\" }}\n onPointerEnter={(event) => hover(i, event)}\n onPointerLeave={() => leave(i)}\n onPointerDown={() => tap(i)}\n >\n <Mascot\n bird={b.bird}\n tone={tone}\n life\n look={looks[i]}\n flying={flying?.index === i}\n bank={flying?.index === i ? flying.bank : 0}\n poked={poked[i]}\n size={120}\n style={{ width: \"100%\", height: \"100%\", display: \"block\", overflow: \"visible\" }}\n />\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/flock/flock.tsx","../src/flock/scenes.tsx"],"sourcesContent":["\"use client\";\n\n// The flock, alive: birds standing on a stage, each at ease in character (Mascot `life`), and the moments between\n// them — two birds glance at each other, the pigeon carries its parcel across, a bird looks up when you come near or tap\n// it. Transform and opacity only: CSS for each bird's own life, a timer for the moments (no frame loop), and nothing at\n// all when the flock is off screen, the tab is hidden or the person asked for less motion.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport type { MascotBird, MascotLook } from \"../mascots\";\nimport { Mascot } from \"../mascots\";\nimport { BEATS, neighbourOf, Prop, receive, type Shown, type Stage } from \"./scenes\";\n\nexport interface FlockBird {\n /** Which bird. */\n bird: MascotBird;\n /** Where its feet are, across the stage: 0 to 100 (% of the stage's width). */\n x: number;\n /** Where its feet are, down the stage: 0 to 100 (% of the stage's height). */\n y: number;\n /** How wide it is: % of the stage's width. */\n size: number;\n}\n\nexport interface FlockMoments {\n /** Two neighbours look at each other now and then. Default `true`. */\n glance?: boolean;\n /** The pigeon, when the flock has one, carries its parcel across to another bird and comes back. Default `true`. */\n courier?: boolean;\n /** A bird looks up when the pointer comes near, and jumps a little when tapped. Default `true`. */\n react?: boolean;\n /**\n * Scenes, true to each bird's promise: the owl reads a book, the flamingo and the lovebird talk with a speech mark, the\n * crane steps and bows, the beaver taps a log, the magpie takes a shiny point, the duck builds, the falcon scans — and the\n * pigeon hands its parcel over, which the receiver opens in its own way. One at a time, at random. Default `false`.\n */\n scenes?: boolean;\n}\n\nexport type FlockProps = Omit<React.ComponentProps<\"div\">, \"children\"> &\n FlockMoments & {\n /** The birds on the stage. */\n birds: readonly FlockBird[];\n /** The stage's shape, width over height (default 16 / 9). It keeps its ratio at any width, so the birds keep their places. */\n ratio?: number;\n /** The birds' colours: the host's accent (`brand`, default) or the Krizaka story's (`own`). */\n tone?: \"brand\" | \"own\";\n /** The source of chance (default `Math.random`): give it a fixed one in a test. */\n random?: () => number;\n /** How lively the moments are: 1 is calm (default), 2 doubles how often neighbours glance and the pigeon delivers. */\n tempo?: number;\n /** A bird the page points at (a product the reader is on): it looks up and jumps once each time it changes. */\n active?: MascotBird | null;\n /** The birds greet the reader once as the flock first comes into view: each jumps in turn, left to right. */\n greet?: boolean;\n };\n\n// @fixed: the rhythm of the moments — how long a glance lasts, how often one happens, how long a delivery takes. A\n// choreography's pace, not a business parameter.\nconst GLANCE_HOLD_MS = [1500, 2400] as const;\nconst GLANCE_EVERY_MS = [4200, 9000] as const;\nconst COURIER_FIRST_MS = 9000;\nconst COURIER_EVERY_MS = [26000, 38000] as const;\nconst FLIGHT_MS = 2600;\nconst HAND_OVER_MS = 1300;\nconst LOOK_BACK_MS = 1600;\n\nconst between = (random: () => number, [lo, hi]: readonly [number, number], tempo = 1) => (lo + random() * (hi - lo)) / tempo;\n// @fixed: the scenes' pace — the wait between two beats, and the rarer long pause.\nconst SCENE_EVERY_MS = [2600, 5200] as const;\nconst SCENE_PAUSE_MS = [8000, 12000] as const;\nconst GREET_STEP_MS = 110;\nconst POKE_MS = 700;\n\n/** `true` while the page may move: no reduced-motion request, the tab visible. */\nfunction useMayMove(): boolean {\n const [may, setMay] = React.useState(false);\n React.useEffect(() => {\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n // The page settles first: `html[data-motion=\"settling\"]` (MotionObserver) holds every loop until it is `ready`.\n const settled = () => document.documentElement.getAttribute(\"data-motion\") !== \"settling\";\n const update = () => setMay(!query.matches && document.visibilityState !== \"hidden\" && settled());\n update();\n query.addEventListener(\"change\", update);\n document.addEventListener(\"visibilitychange\", update);\n const watch = typeof MutationObserver === \"undefined\" ? null : new MutationObserver(update);\n watch?.observe(document.documentElement, { attributes: true, attributeFilter: [\"data-motion\"] });\n return () => {\n query.removeEventListener(\"change\", update);\n document.removeEventListener(\"visibilitychange\", update);\n watch?.disconnect();\n };\n }, []);\n return may;\n}\n\n/** `true` while the element is on screen. */\nfunction useOnScreen(ref: React.RefObject<Element | null>): boolean {\n const [on, setOn] = React.useState(false);\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(([entry]) => setOn(Boolean(entry?.isIntersecting)), { threshold: 0.1 });\n observer.observe(el);\n return () => observer.disconnect();\n }, [ref]);\n return on;\n}\n\n/**\n * The flock on its stage, alive. Decorative (`aria-hidden`): put the words beside it. Each bird idles in character; every\n * few seconds two neighbours glance at each other; every half minute the pigeon carries its parcel to another bird and\n * returns; a bird looks up when you come near. All of it pauses off screen and in a hidden tab, and the flock is still\n * under `prefers-reduced-motion`.\n */\nexport function Flock({ birds, ratio = 16 / 9, tone = \"brand\", glance = true, courier = true, react = true, scenes = false, random = Math.random, tempo = 1, active = null, greet = false, className, style, ...props }: FlockProps) {\n const stage = React.useRef<HTMLDivElement>(null);\n const bodies = React.useRef<(HTMLDivElement | null)[]>([]);\n const may = useMayMove();\n const onScreen = useOnScreen(stage);\n const running = may && onScreen;\n const [looks, setLooks] = React.useState<Record<number, MascotLook>>({});\n const [flying, setFlying] = React.useState<{ index: number; bank: number } | null>(null);\n const [poked, setPoked] = React.useState<Record<number, boolean>>({});\n const [shown, setShown] = React.useState<Shown[]>([]);\n const [empty, setEmpty] = React.useState<Record<number, boolean>>({});\n // Birds a scene holds (a glance or a trip leaves them alone), and the scene or the trip in progress.\n const held = React.useRef(new Set<number>());\n const busy = React.useRef<\"scene\" | \"trip\" | null>(null);\n const ids = React.useRef(0);\n\n // Left to right: a bird's neighbours are the birds beside it on the stage.\n const order = React.useMemo(() => birds.map((_, i) => i).sort((a, b) => birds[a]!.x - birds[b]!.x), [birds]);\n const look = React.useCallback((index: number, to: MascotLook) => setLooks((l) => (l[index] === to ? l : { ...l, [index]: to })), []);\n const rest = React.useCallback((...indexes: number[]) => setLooks((l) => Object.fromEntries(Object.entries(l).filter(([k]) => !indexes.includes(Number(k))))), []);\n\n // What a scene can do, bound to one run of an effect: every timer and animation it starts ends with the run.\n const stageFor = React.useCallback((run: { timers: Set<ReturnType<typeof setTimeout>>; anims: Set<Animation> }): Stage => {\n const later = (fn: () => void, ms: number) => {\n const t = setTimeout(() => {\n run.timers.delete(t);\n fn();\n }, ms);\n run.timers.add(t);\n };\n const poke = (index: number, ms = POKE_MS) => {\n setPoked((p) => ({ ...p, [index]: true }));\n later(() => setPoked((p) => ({ ...p, [index]: false })), ms);\n };\n const show = (index: number, kind: Shown[\"kind\"], ms: number, side?: 1 | -1, mark?: string) => {\n const item: Shown = { id: ++ids.current, at: index, kind, ms, side, mark };\n setShown((all) => [...all, item]);\n later(() => setShown((all) => all.filter((x) => x.id !== item.id)), ms);\n };\n return {\n birds,\n order,\n random,\n look,\n rest,\n poke,\n show,\n say: (index, mark, ms) => show(index, \"say\", ms, undefined, mark),\n wait: (ms) => new Promise<void>((resolve) => later(resolve, ms)),\n move: async (index, keyframes, ms) => {\n const el = bodies.current[index];\n if (!el || typeof el.animate !== \"function\") return;\n const animation = el.animate(keyframes, { duration: ms });\n run.anims.add(animation);\n await animation.finished.catch(() => undefined);\n run.anims.delete(animation);\n },\n };\n }, [birds, order, random, look, rest]);\n\n // Glances: two neighbours turn towards each other, hold, and look away.\n React.useEffect(() => {\n if (!running || !glance || order.length < 2) return;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let back: ReturnType<typeof setTimeout> | undefined;\n const next = () => {\n timer = setTimeout(() => {\n const at = Math.floor(random() * (order.length - 1));\n const [a, b] = [order[at]!, order[at + 1]!];\n if (held.current.has(a) || held.current.has(b)) return next();\n look(a, \"right\");\n look(b, \"left\");\n back = setTimeout(() => {\n rest(a, b);\n next();\n }, between(random, GLANCE_HOLD_MS));\n }, between(random, GLANCE_EVERY_MS, tempo));\n };\n next();\n return () => {\n clearTimeout(timer);\n clearTimeout(back);\n };\n }, [running, glance, order, random, tempo, look, rest]);\n\n // The delivery: the pigeon takes its parcel across to the farthest bird, hands it over, and flies back.\n React.useEffect(() => {\n const pigeon = birds.findIndex((b) => b.bird === \"pigeon\");\n if (!running || !courier || pigeon < 0 || birds.length < 2) return;\n let alive = true;\n const heldNow = held.current;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let animation: Animation | undefined;\n const run = { timers: new Set<ReturnType<typeof setTimeout>>(), anims: new Set<Animation>() };\n // The farthest bird from the pigeon, so the parcel crosses the whole stage.\n const from = birds[pigeon]!;\n const target = birds.reduce((far, b, i) => (i !== pigeon && Math.abs(b.x - from.x) > Math.abs(birds[far]!.x - from.x) ? i : far), pigeon === 0 ? 1 : 0);\n const wait = (ms: number) => new Promise<void>((resolve) => (timer = setTimeout(resolve, ms)));\n const trip = async () => {\n // With scenes, the trip waits for the beat in progress and holds the stage while it lasts.\n while (alive && scenes && busy.current === \"scene\") await wait(400);\n if (!alive) return;\n busy.current = \"trip\";\n const el = bodies.current[pigeon];\n const box = stage.current?.getBoundingClientRect();\n if (!el || !box || typeof el.animate !== \"function\") return;\n const to = birds[target]!;\n const side = to.x > from.x ? 1 : -1;\n // It lands beside the receiver, not on it.\n const dx = ((to.x - from.x) / 100) * box.width - side * (to.size / 100) * box.width * 0.55;\n const lift = (from.size / 100) * box.width * 0.35;\n const fly = async (fromX: number, toX: number) => {\n setFlying({ index: pigeon, bank: Math.sign(toX - fromX) });\n animation = el.animate(\n [\n { transform: `translate(${fromX}px, 0)`, easing: \"ease-out\" },\n { transform: `translate(${(fromX + toX) / 2}px, ${-lift}px)`, easing: \"ease-in\", offset: 0.5 },\n { transform: `translate(${toX}px, 0)` },\n ],\n { duration: FLIGHT_MS, fill: \"forwards\" },\n );\n await animation.finished.catch(() => undefined);\n setFlying(null);\n };\n look(target, side > 0 ? \"left\" : \"right\");\n held.current.add(target);\n await fly(0, dx);\n if (!alive) return;\n // The hand-over: the receiver looks at the pigeon, the pigeon hops on the doorstep.\n setPoked((p) => ({ ...p, [pigeon]: true }));\n if (scenes) {\n // …and the parcel changes hands: the receiver takes it and reacts in character, the pigeon flies back light.\n setEmpty((e) => ({ ...e, [pigeon]: true }));\n const reaction = receive(stageFor(run), target, pigeon);\n await wait(HAND_OVER_MS);\n if (!alive) return;\n setPoked((p) => ({ ...p, [pigeon]: false }));\n await reaction;\n } else {\n await wait(HAND_OVER_MS);\n if (!alive) return;\n setPoked((p) => ({ ...p, [pigeon]: false }));\n }\n if (!alive) return;\n look(target, \"up\");\n await fly(dx, 0);\n animation?.cancel();\n setEmpty((e) => ({ ...e, [pigeon]: false }));\n rest(target);\n };\n const schedule = (ms: number) => {\n timer = setTimeout(async () => {\n await trip();\n busy.current = null;\n held.current.delete(target);\n if (alive) schedule(between(random, COURIER_EVERY_MS, tempo));\n }, ms);\n };\n schedule(COURIER_FIRST_MS / tempo);\n return () => {\n alive = false;\n clearTimeout(timer);\n animation?.cancel();\n run.timers.forEach(clearTimeout);\n run.anims.forEach((a) => a.cancel());\n if (scenes) {\n setShown([]);\n setEmpty({});\n heldNow.clear();\n busy.current = null;\n }\n setFlying(null);\n };\n }, [running, courier, birds, random, tempo, scenes, stageFor, look, rest]);\n\n // The scenes: one beat at a time, picked at random from what the flock holds — never the same bird twice in a row, never\n // at a regular beat (short waits, now and then a long pause) — so the minute is never the same twice.\n React.useEffect(() => {\n if (!running || !scenes || birds.length < 1) return;\n let alive = true;\n const heldNow = held.current;\n const run = { timers: new Set<ReturnType<typeof setTimeout>>(), anims: new Set<Animation>() };\n const st = stageFor(run);\n const beats = BEATS.flatMap((beat) => birds.flatMap((b, i) => (b.bird === beat.bird ? [{ beat, index: i }] : [])));\n if (!beats.length) return;\n let last = -1;\n const next = async () => {\n const long = random() < 0.2;\n await st.wait(between(random, long ? SCENE_PAUSE_MS : SCENE_EVERY_MS, tempo));\n while (alive && busy.current === \"trip\") await st.wait(600);\n if (!alive) return;\n const pool = beats.filter((x) => x.index !== last);\n const pick = (pool.length ? pool : beats)[Math.floor(random() * (pool.length ? pool.length : beats.length))]!;\n last = pick.index;\n busy.current = \"scene\";\n // The scene's birds are held, so no glance cuts across it.\n const near = neighbourOf(st, pick.index);\n held.current.add(pick.index);\n if (near !== null) held.current.add(near);\n await pick.beat.run(st, pick.index);\n held.current.delete(pick.index);\n if (near !== null) held.current.delete(near);\n if (busy.current === \"scene\") busy.current = null;\n if (alive) void next();\n };\n void next();\n return () => {\n alive = false;\n run.timers.forEach(clearTimeout);\n run.anims.forEach((a) => a.cancel());\n setShown([]);\n heldNow.clear();\n busy.current = null;\n };\n }, [running, scenes, birds, random, tempo, stageFor]);\n\n // The greeting: the first time the flock is on screen, each bird jumps in turn.\n const greeted = React.useRef(false);\n React.useEffect(() => {\n if (!running || !greet || greeted.current) return;\n greeted.current = true;\n const timers: ReturnType<typeof setTimeout>[] = [];\n order.forEach((index, n) => {\n timers.push(setTimeout(() => setPoked((p) => ({ ...p, [index]: true })), n * GREET_STEP_MS));\n timers.push(setTimeout(() => setPoked((p) => ({ ...p, [index]: false })), n * GREET_STEP_MS + POKE_MS));\n });\n return () => timers.forEach(clearTimeout);\n }, [running, greet, order]);\n\n // The bird the page points at looks up and jumps.\n React.useEffect(() => {\n const index = active ? birds.findIndex((b) => b.bird === active) : -1;\n if (!running || index < 0) return;\n const start = setTimeout(() => {\n look(index, \"up\");\n setPoked((p) => ({ ...p, [index]: true }));\n }, 0);\n const t = setTimeout(() => setPoked((p) => ({ ...p, [index]: false })), POKE_MS);\n return () => {\n clearTimeout(start);\n clearTimeout(t);\n setPoked((p) => ({ ...p, [index]: false }));\n rest(index);\n };\n }, [active, running, birds, look, rest]);\n\n // A bird looks up when you come near, and jumps when you tap it.\n const hover = (index: number, event: React.PointerEvent) => {\n if (!running || !react || event.pointerType !== \"mouse\") return;\n look(index, \"up\");\n };\n const leave = (index: number) => {\n if (!react) return;\n rest(index);\n };\n const tap = (index: number) => {\n if (!running || !react) return;\n look(index, \"up\");\n setPoked((p) => ({ ...p, [index]: true }));\n setTimeout(() => {\n setPoked((p) => ({ ...p, [index]: false }));\n rest(index);\n }, LOOK_BACK_MS);\n };\n\n return (\n <div\n ref={stage}\n aria-hidden\n data-flock=\"\"\n data-running={running ? \"\" : undefined}\n data-motion-scope=\"\"\n className={cn(\"relative w-full\", className)}\n style={{ aspectRatio: String(ratio), containerType: \"inline-size\", ...style }}\n {...props}\n >\n {birds.map((b, i) => (\n <div\n key={`${b.bird}-${i}`}\n ref={(el) => {\n bodies.current[i] = el;\n }}\n data-flock-bird={b.bird}\n className=\"absolute touch-manipulation\"\n style={{ left: `${b.x - b.size / 2}%`, width: `${b.size}%`, top: `calc(${b.y}% - ${b.size * 0.9}cqw)`, aspectRatio: \"1\", pointerEvents: react ? \"auto\" : \"none\" }}\n onPointerEnter={(event) => hover(i, event)}\n onPointerLeave={() => leave(i)}\n onPointerDown={() => tap(i)}\n >\n <Mascot\n bird={b.bird}\n tone={tone}\n life\n look={looks[i]}\n flying={flying?.index === i}\n bank={flying?.index === i ? flying.bank : 0}\n poked={poked[i]}\n carrying={!empty[i]}\n size={120}\n style={{ width: \"100%\", height: \"100%\", display: \"block\", overflow: \"visible\" }}\n />\n {shown\n .filter((x) => x.at === i)\n .map((x) => (\n <Prop key={x.id} shown={x} size={b.size} />\n ))}\n </div>\n ))}\n </div>\n );\n}\n","\"use client\";\n\n// The flock's scenes: what a bird does between the idle motions, each one true to the promise it carries — the owl reads\n// (a book, a leaf turned), the flamingo and the lovebird answer (a speech mark, a reply), the crane steps and bows, the\n// beaver carries a log and taps it, the magpie spots a shiny point and takes it, the duck builds, the falcon scans — and the\n// pigeon's parcel changes hands: the receiver reacts in its own way. A director picks one beat at a time from what the\n// flock holds, with chance in the waits and in the choice, so it never loops the same minute twice. Transform and opacity\n// only (Web Animations on a few small elements, timers between beats); nothing runs off screen or under reduced motion.\nimport * as React from \"react\";\n\nimport type { MascotBird, MascotLook } from \"../mascots\";\nimport { PARCEL } from \"../mascots/geometry\";\n\nexport type PropKind = \"say\" | \"book\" | \"log\" | \"glint\" | \"gift\";\n\n/** A small thing a bird shows for a while: a speech mark, a book, a log, a shiny point, a parcel. */\nexport interface Shown {\n id: number;\n /** Index of the bird it belongs to. */\n at: number;\n kind: PropKind;\n /** How long it stays (ms). */\n ms: number;\n /** The mark of a speech bubble. */\n mark?: string;\n /** Which side it comes from (1: right, -1: left). */\n side?: 1 | -1;\n}\n\n/** What a beat can do on the stage (built by `Flock`; every wait ends when the flock stops). */\nexport interface Stage {\n birds: readonly { bird: MascotBird; x: number; y: number; size: number }[];\n /** Indexes left to right. */\n order: readonly number[];\n random: () => number;\n look: (index: number, to: MascotLook) => void;\n rest: (...indexes: number[]) => void;\n poke: (index: number, ms?: number) => void;\n say: (index: number, mark: string, ms: number) => void;\n show: (index: number, kind: PropKind, ms: number, side?: 1 | -1) => void;\n /** Move a bird's body for a while (transform only). */\n move: (index: number, keyframes: Keyframe[], ms: number) => Promise<void>;\n wait: (ms: number) => Promise<void>;\n}\n\nconst side = (s: Stage, i: number, j: number): 1 | -1 => (s.birds[j]!.x >= s.birds[i]!.x ? 1 : -1);\nconst towards = (s: Stage, i: number, j: number): MascotLook => (side(s, i, j) > 0 ? \"right\" : \"left\");\n/** Where a bird is among its neighbours, left to right: the one beside it (the nearer one when there are two). */\nexport function neighbourOf(s: Stage, i: number): number | null {\n const at = s.order.indexOf(i);\n const near = [s.order[at - 1], s.order[at + 1]].filter((n): n is number => n !== undefined);\n if (!near.length) return null;\n return near.reduce((a, b) => (Math.abs(s.birds[a]!.x - s.birds[i]!.x) <= Math.abs(s.birds[b]!.x - s.birds[i]!.x) ? a : b));\n}\n\n// @fixed: the choreography's pace — how long each beat lasts. A rhythm to the eye, not a business parameter.\nconst BOOK_MS = 4800;\nconst LOG_MS = 3800;\nconst GLINT_MS = 3400;\nconst SAY_MS = 1500;\n\n/** The owl reads: it looks down at its book, a leaf turns, and it turns another. A neighbour glances over. */\nasync function read(s: Stage, i: number) {\n const j = neighbourOf(s, i);\n s.look(i, \"left\");\n s.show(i, \"book\", BOOK_MS);\n await s.wait(BOOK_MS * 0.45);\n if (j !== null && s.random() < 0.5) {\n s.look(j, towards(s, j, i));\n await s.wait(1100);\n s.rest(j);\n }\n await s.wait(BOOK_MS * 0.5);\n s.rest(i);\n}\n\n/** The flamingo or the lovebird speaks; its neighbour listens, then answers, and they both light up. */\nasync function chat(s: Stage, i: number) {\n const j = neighbourOf(s, i);\n s.look(i, j === null ? \"up\" : towards(s, i, j));\n s.say(i, \"…\", SAY_MS);\n await s.wait(SAY_MS * 0.6);\n if (j === null) {\n await s.wait(SAY_MS * 0.6);\n s.rest(i);\n return;\n }\n s.look(j, towards(s, j, i));\n await s.wait(SAY_MS * 0.7);\n s.say(j, s.random() < 0.5 ? \"!\" : \"?\", SAY_MS);\n s.poke(j);\n await s.wait(SAY_MS * 0.5);\n s.poke(i);\n await s.wait(SAY_MS * 0.7);\n s.rest(i, j);\n}\n\n/** The crane steps out of the line, bows to its neighbour, and steps back. */\nasync function bow(s: Stage, i: number) {\n const j = neighbourOf(s, i);\n const dir = j === null ? 1 : side(s, i, j);\n const step = `${(s.birds[i]!.size * 0.14 * dir).toFixed(2)}cqw`;\n const lean = `rotate(${dir * 11}deg)`;\n const at = (x: string, r: string) => `translateX(${x}) ${r}`;\n const run = s.move(\n i,\n [\n { transform: at(\"0cqw\", \"rotate(0deg)\"), easing: \"ease-in-out\" },\n { transform: at(step, \"rotate(0deg)\"), offset: 0.22, easing: \"ease-in-out\" },\n { transform: at(step, lean), offset: 0.42, easing: \"ease-in-out\" },\n { transform: at(step, lean), offset: 0.6, easing: \"ease-in-out\" },\n { transform: at(step, \"rotate(0deg)\"), offset: 0.74, easing: \"ease-in-out\" },\n { transform: at(\"0cqw\", \"rotate(0deg)\") },\n ],\n 3800,\n );\n if (j !== null) {\n await s.wait(1700);\n s.look(j, towards(s, j, i));\n await s.wait(1200);\n s.poke(j);\n await s.wait(500);\n s.rest(j);\n }\n await run;\n}\n\n/** The beaver brings a log, taps it into place three times, and takes it away. */\nasync function tap(s: Stage, i: number) {\n s.show(i, \"log\", LOG_MS, s.birds[i]!.x > 50 ? 1 : -1);\n await s.wait(LOG_MS * 0.3);\n for (let n = 0; n < 3; n++) {\n s.poke(i, 420);\n await s.wait(520);\n }\n await s.wait(LOG_MS * 0.3);\n}\n\n/** The magpie sees something shiny on the ground, looks, hops, and takes it. */\nasync function shine(s: Stage, i: number) {\n const dir: 1 | -1 = s.birds[i]!.x > 50 ? -1 : 1;\n const to: MascotLook = dir > 0 ? \"right\" : \"left\";\n s.show(i, \"glint\", GLINT_MS, dir);\n await s.wait(GLINT_MS * 0.28);\n s.look(i, to);\n await s.wait(GLINT_MS * 0.3);\n s.poke(i);\n await s.wait(GLINT_MS * 0.25);\n s.look(i, \"up\");\n await s.wait(GLINT_MS * 0.2);\n s.rest(i);\n}\n\n/** The duck builds: quick nods in a burst, like typing a block into place. */\nasync function build(s: Stage, i: number) {\n for (let n = 0; n < 4; n++) {\n s.poke(i, 300);\n await s.wait(380);\n }\n}\n\n/** The falcon watches: a slow scan, left then right, and a look up. */\nasync function scan(s: Stage, i: number) {\n for (const to of [\"left\", \"up\", \"right\"] as const) {\n s.look(i, to);\n await s.wait(1100);\n }\n s.rest(i);\n}\n\n/** The pigeon's parcel has just been handed over: the receiver reacts in its own way (about 2 s). */\nexport async function receive(s: Stage, i: number, from: number) {\n const bird = s.birds[i]!.bird;\n s.look(i, towards(s, i, from));\n s.show(i, \"gift\", 2400);\n await s.wait(350);\n if (bird === \"crane\") await bow(s, i);\n else if (bird === \"magpie\") {\n s.poke(i);\n await s.wait(700);\n s.show(i, \"glint\", GLINT_MS * 0.6, side(s, i, from));\n await s.wait(1200);\n } else if (bird === \"beaver\" || bird === \"duck\") {\n s.poke(i, 420);\n await s.wait(520);\n s.poke(i, 420);\n await s.wait(900);\n } else if (bird === \"owl\") {\n s.say(i, \"?\", SAY_MS);\n await s.wait(900);\n s.poke(i);\n await s.wait(700);\n } else {\n s.say(i, \"!\", SAY_MS);\n s.poke(i);\n await s.wait(1500);\n }\n}\n\nexport interface Beat {\n id: string;\n bird: MascotBird;\n run: (s: Stage, index: number) => Promise<void>;\n}\n\n/** What each bird of the flock can do on its own (the pigeon's trip is the flock's courier). */\nexport const BEATS: readonly Beat[] = [\n { id: \"read\", bird: \"owl\", run: read },\n { id: \"chat\", bird: \"flamingo\", run: chat },\n { id: \"chat\", bird: \"lovebird\", run: chat },\n { id: \"bow\", bird: \"crane\", run: bow },\n { id: \"tap\", bird: \"beaver\", run: tap },\n { id: \"shine\", bird: \"magpie\", run: shine },\n { id: \"build\", bird: \"duck\", run: build },\n { id: \"scan\", bird: \"falcon\", run: scan },\n];\n\n// ─── The small things a bird shows ───────────────────────────────────────────────────────────────\n\nconst PAPER = \"var(--kz-surface-1)\";\nconst INK = \"var(--kz-text-primary)\";\nconst LINE = \"var(--kz-border-strong, currentColor)\";\n\n/** One thing, in its own frame: it comes in, stays for `ms`, and goes (opacity and transform only). */\nfunction lifeFrames(from: string, to: string): Keyframe[] {\n return [\n { opacity: 0, transform: from, offset: 0 },\n { opacity: 1, transform: \"none\", offset: 0.14 },\n { opacity: 1, transform: \"none\", offset: 0.84 },\n { opacity: 0, transform: to, offset: 1 },\n ];\n}\n\nconst LEAF: Keyframe[] = [\n { transform: \"scaleX(1)\", offset: 0 },\n { transform: \"scaleX(1)\", offset: 0.25 },\n { transform: \"scaleX(-1)\", offset: 0.38 },\n { transform: \"scaleX(1)\", offset: 0.39 },\n { transform: \"scaleX(1)\", offset: 0.62 },\n { transform: \"scaleX(-1)\", offset: 0.75 },\n { transform: \"scaleX(-1)\", offset: 1 },\n];\n\nexport function Prop({ shown, size }: { shown: Shown; size: number }) {\n const ref = React.useRef<HTMLDivElement>(null);\n const leaf = React.useRef<HTMLDivElement>(null);\n const dir = shown.side ?? 1;\n React.useEffect(() => {\n const el = ref.current;\n if (!el || typeof el.animate !== \"function\") return;\n const from: Record<PropKind, [string, string]> = {\n say: [\"translateY(30%) scale(.5)\", \"translateY(-12%) scale(.9)\"],\n book: [\"translateY(40%) scale(.8)\", \"translateY(20%) scale(.9)\"],\n log: [`translateX(${190 * dir}%)`, `translateX(${190 * dir}%)`],\n glint: [\"scale(.2) rotate(-60deg)\", `translate(${-90 * dir}%, -170%) scale(.2) rotate(60deg)`],\n gift: [\"translateY(40%) scale(.3)\", \"translateY(-30%) scale(1.4)\"],\n };\n const [a, b] = from[shown.kind];\n const animations = [el.animate(lifeFrames(a, b), { duration: shown.ms, fill: \"both\", easing: \"ease-out\" })];\n if (shown.kind === \"book\" && leaf.current) animations.push(leaf.current.animate(LEAF, { duration: shown.ms, fill: \"both\", easing: \"ease-in-out\" }));\n if (shown.kind === \"glint\") animations.push(el.firstElementChild!.animate([{ transform: \"scale(1)\" }, { transform: \"scale(1.35)\" }, { transform: \"scale(1)\" }], { duration: 700, iterations: Math.ceil(shown.ms / 700), easing: \"ease-in-out\" }));\n return () => animations.forEach((x) => x.cancel());\n }, [shown, dir]);\n\n const unit = (n: number) => `calc(${size}cqw * ${n})`;\n const base: React.CSSProperties = { position: \"absolute\", pointerEvents: \"none\", opacity: 0 };\n\n if (shown.kind === \"say\")\n return (\n <div ref={ref} data-flock-prop=\"say\" style={{ ...base, left: \"58%\", top: \"-6%\", width: unit(0.34), height: unit(0.24), transformOrigin: \"20% 100%\" }}>\n <span\n style={{ position: \"absolute\", inset: 0, display: \"grid\", placeItems: \"center\", background: PAPER, border: `1.5px solid ${LINE}`, borderRadius: \"999px\", color: INK, font: `600 ${unit(0.17)}/1 var(--font-mono, ui-monospace, monospace)` }}\n >\n {shown.mark ?? \"…\"}\n </span>\n <span style={{ position: \"absolute\", left: \"14%\", bottom: \"-12%\", width: unit(0.07), height: unit(0.07), background: PAPER, borderRight: `1.5px solid ${LINE}`, borderBottom: `1.5px solid ${LINE}`, transform: \"rotate(45deg)\" }} />\n </div>\n );\n\n if (shown.kind === \"book\")\n return (\n <div ref={ref} data-flock-prop=\"book\" style={{ ...base, left: \"17%\", bottom: \"-2%\", width: \"66%\", height: unit(0.2), transformOrigin: \"50% 100%\" }}>\n {[0, 1].map((n) => (\n <span key={n} style={{ position: \"absolute\", top: 0, bottom: 0, [n ? \"right\" : \"left\"]: 0, width: \"50%\", background: `repeating-linear-gradient(${PAPER} 0 18%, ${LINE} 18% 24%)`, border: `1.5px solid ${LINE}`, borderRadius: n ? \"0 3px 3px 0\" : \"3px 0 0 3px\" }} />\n ))}\n <div ref={leaf} style={{ position: \"absolute\", top: 0, bottom: 0, left: \"50%\", width: \"50%\", transformOrigin: \"0 50%\", background: PAPER, border: `1.5px solid ${LINE}`, borderRadius: \"0 3px 3px 0\" }} />\n </div>\n );\n\n if (shown.kind === \"log\")\n return (\n <div ref={ref} data-flock-prop=\"log\" style={{ ...base, left: \"22%\", bottom: \"-3%\", width: \"56%\", height: unit(0.17), background: PARCEL[2], borderRadius: \"999px\", boxShadow: `inset -${unit(0.04)} 0 0 ${PARCEL[1]}` }}>\n <span style={{ position: \"absolute\", left: 0, top: 0, bottom: 0, aspectRatio: \"1\", borderRadius: \"50%\", background: `radial-gradient(${PARCEL[0]} 0 25%, ${PARCEL[1]} 26% 55%, ${PARCEL[2]} 56%)`, border: `1px solid ${PARCEL[2]}` }} />\n </div>\n );\n\n if (shown.kind === \"glint\")\n return (\n <div ref={ref} data-flock-prop=\"glint\" style={{ ...base, [dir > 0 ? \"left\" : \"right\"]: \"94%\", bottom: \"2%\", width: unit(0.2), height: unit(0.2) }}>\n <span style={{ position: \"absolute\", inset: 0, background: PARCEL[0], clipPath: \"polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%)\" }} />\n </div>\n );\n\n return (\n <div ref={ref} data-flock-prop=\"gift\" style={{ ...base, left: \"58%\", top: \"2%\", width: unit(0.26), height: unit(0.22), background: PARCEL[0], border: `1.5px solid ${PARCEL[2]}`, borderRadius: 2 }}>\n <span style={{ position: \"absolute\", left: \"44%\", top: 0, bottom: 0, width: \"12%\", background: PARCEL[2] }} />\n <span style={{ position: \"absolute\", top: \"42%\", left: 0, right: 0, height: \"16%\", background: PARCEL[2] }} />\n </div>\n );\n}\n"],"mappings":"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","names":["React","jsx","jsxs","side","tap"]}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Mascot
4
- } from "./chunk-M4DBVG43.js";
4
+ } from "./chunk-MHUUNC5W.js";
5
5
  import {
6
6
  cn
7
7
  } from "./chunk-WU4VLSEA.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Mascot
4
- } from "./chunk-EZC54B5C.js";
4
+ } from "./chunk-MIMOTE4W.js";
5
5
 
6
6
  // src/mascot-state/mascot-state.tsx
7
7
  import { tv } from "tailwind-variants";
package/dist/mascots.d.ts CHANGED
@@ -43,6 +43,8 @@ type MascotProps = Omit<React.ComponentProps<"svg">, "children"> & {
43
43
  flying?: boolean;
44
44
  /** Which way it leans in flight, -1 (left) to 1 (right). */
45
45
  bank?: number;
46
+ /** Whether the pigeon holds its parcel (default `true`): a flock hands it over and the bird flies back light. */
47
+ carrying?: boolean;
46
48
  /** A tap or a poke just happened (`life`): a small jump. Set it for a moment, then unset. */
47
49
  poked?: boolean;
48
50
  };
@@ -50,7 +52,7 @@ type MascotProps = Omit<React.ComponentProps<"svg">, "children"> & {
50
52
  * One of the nine Krizaka figures in one mood — for the moments a product speaks to a person: a welcome, a long wait,
51
53
  * a success, an empty list, an error. Drawn in the host's brand colours by default (`tone="own"` for the story's).
52
54
  */
53
- declare function Mascot({ bird, mood, tone, size, animated, title, life, phase, look, flying, bank, poked, className, style, ...props }: MascotProps): React.JSX.Element;
55
+ declare function Mascot({ bird, mood, tone, size, animated, title, life, phase, look, flying, bank, poked, carrying, className, style, ...props }: MascotProps): React.JSX.Element;
54
56
 
55
57
  type PhoenixProps = Omit<React.ComponentProps<"svg">, "children"> & {
56
58
  /** `own` (default): the violet wing and the gold wing of the Krizaka story. `brand`: the host's accent and accent-2. */
package/dist/mascots.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  MASCOT_LOOKS,
5
5
  MASCOT_MOODS,
6
6
  Mascot
7
- } from "./chunk-EZC54B5C.js";
7
+ } from "./chunk-MIMOTE4W.js";
8
8
 
9
9
  // src/mascots/phoenix.tsx
10
10
  import { useId } from "react";
package/dist/nav-bar.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  GitHubGlyph,
5
5
  familyLabels,
6
6
  sitesByGroup
7
- } from "./chunk-7JFHTPI3.js";
7
+ } from "./chunk-P4TTKYC4.js";
8
8
  import {
9
9
  LanguageSwitch
10
10
  } from "./chunk-VPO27AFS.js";
@@ -12,7 +12,6 @@ declare const siteFooter: tailwind_variants.TVReturnType<{
12
12
  app: {
13
13
  root: string;
14
14
  inner: string;
15
- bottom: string;
16
15
  };
17
16
  };
18
17
  }, {
@@ -41,7 +40,6 @@ declare const siteFooter: tailwind_variants.TVReturnType<{
41
40
  app: {
42
41
  root: string;
43
42
  inner: string;
44
- bottom: string;
45
43
  };
46
44
  };
47
45
  }, {
@@ -70,7 +68,6 @@ declare const siteFooter: tailwind_variants.TVReturnType<{
70
68
  app: {
71
69
  root: string;
72
70
  inner: string;
73
- bottom: string;
74
71
  };
75
72
  };
76
73
  }, {
@@ -104,6 +101,11 @@ type SiteFooterProps = Omit<React.ComponentProps<"footer">, "children"> & {
104
101
  version?: string;
105
102
  /** The environment, when it is not production (`DEV`). */
106
103
  env?: string;
104
+ /**
105
+ * The path of the page being read on this site (`/en/story`, `/blog/…`): the company link that points to this very
106
+ * page says so (`aria-current="page"`, a visible state) and a click on it scrolls to the top instead of reloading.
107
+ */
108
+ path?: string;
107
109
  /**
108
110
  * Shows the family in columns (the Krizaka sites: www, ui., java.). A product is independent once deployed: pass
109
111
  * `family={false}` and the footer holds only its own columns, the legal links, the version and one publisher line —
@@ -123,7 +125,7 @@ type SiteFooterProps = Omit<React.ComponentProps<"footer">, "children"> & {
123
125
  variant?: "site" | "docs" | "app";
124
126
  };
125
127
  /** The footer of a Krizaka site, one band: its own columns and the family's, then one line — signature, version, Montréal, legal. */
126
- declare function SiteFooter({ current, labels, children, version, env, legal, family: familyProp, variant, className, ...props }: SiteFooterProps): React.JSX.Element;
128
+ declare function SiteFooter({ current, labels, children, version, env, path, legal, family: familyProp, variant, className, ...props }: SiteFooterProps): React.JSX.Element;
127
129
  declare namespace SiteFooter {
128
130
  var Column: typeof SiteFooterColumn;
129
131
  var Link: typeof SiteFooterLink;
@@ -5,7 +5,7 @@ import {
5
5
  familyLabels,
6
6
  siteById,
7
7
  sitesByGroup
8
- } from "./chunk-7JFHTPI3.js";
8
+ } from "./chunk-P4TTKYC4.js";
9
9
  import {
10
10
  KrizakaLogo
11
11
  } from "./chunk-4E5IUZHR.js";
@@ -25,10 +25,10 @@ var siteFooter = tv({
25
25
  column: "grid min-w-0 content-start gap-3",
26
26
  title: "text-[11px] font-semibold text-fg-secondary",
27
27
  list: "grid min-w-0 gap-2",
28
- link: "inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=true]:text-fg aria-[current=true]:font-semibold",
28
+ link: "inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=page]:font-semibold aria-[current=true]:text-fg aria-[current=true]:font-semibold",
29
29
  mark: "flex h-4 w-4 shrink-0 items-center justify-center text-fg",
30
30
  tag: "rounded-sm bg-surface-3 px-1.5 py-px text-[10px] font-semibold text-fg-secondary",
31
- bottom: "flex flex-wrap items-center gap-x-5 gap-y-3 border-t border-border-subtle pt-6 text-xs text-fg-secondary",
31
+ bottom: "flex flex-wrap items-center gap-x-5 gap-y-3 text-xs text-fg-secondary",
32
32
  signature: "inline-flex items-center gap-2 rounded-md font-medium text-fg no-underline hover:text-fg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
33
33
  version: "rounded-sm border border-border-subtle bg-surface-2 px-2 py-0.5 font-mono text-[11px] text-fg-secondary",
34
34
  legal: "flex flex-wrap items-center gap-x-4 gap-y-2 sm:ml-auto"
@@ -44,19 +44,33 @@ var siteFooter = tv({
44
44
  },
45
45
  app: {
46
46
  root: "bg-transparent",
47
- inner: "gap-0 py-3",
48
- bottom: "border-t-0 pt-0"
47
+ inner: "gap-0 py-3"
49
48
  }
50
49
  }
51
50
  },
52
51
  defaultVariants: { variant: "site" }
53
52
  });
53
+ var bare = (p) => p.replace(/^\/(en|fr)(?=\/|$)/, "").replace(/\/+$/, "") || "/";
54
+ function isThisPage(href, siteUrl, path) {
55
+ try {
56
+ const target = new URL(href);
57
+ return target.host === new URL(siteUrl).host && bare(target.pathname) === bare(path.split(/[?#]/)[0]);
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ function backToTop(event) {
63
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;
64
+ event.preventDefault();
65
+ window.scrollTo({ top: 0, behavior: "auto" });
66
+ }
54
67
  function SiteFooter({
55
68
  current,
56
69
  labels = familyLabels.en,
57
70
  children,
58
71
  version,
59
72
  env,
73
+ path,
60
74
  legal,
61
75
  family: familyProp = true,
62
76
  variant = "site",
@@ -73,6 +87,7 @@ function SiteFooter({
73
87
  const own = React.Children.toArray(children).length > 0;
74
88
  const lang = labels.lang ?? "en";
75
89
  const company = labels.company ?? familyLabels.en.company;
90
+ const here = (href) => path !== void 0 && isThisPage(href, site.url, path);
76
91
  const groups = sitesByGroup();
77
92
  const columns = [
78
93
  ...groups.filter((g) => g.group === "products"),
@@ -97,7 +112,16 @@ function SiteFooter({
97
112
  ] }, group)),
98
113
  /* @__PURE__ */ jsxs("div", { className: s.column(), children: [
99
114
  /* @__PURE__ */ jsx("p", { id: `${id}-krizaka`, className: s.title(), children: labels.groups.krizaka }),
100
- /* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-krizaka`, className: s.list(), children: companyLinks.map((l) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: l.url[lang], className: s.link(), children: company[l.id] }) }, l.id)) })
115
+ /* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-krizaka`, className: s.list(), children: companyLinks.map((l) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
116
+ "a",
117
+ {
118
+ href: l.url[lang],
119
+ "aria-current": here(l.url[lang]) ? "page" : void 0,
120
+ onClick: here(l.url[lang]) ? backToTop : void 0,
121
+ className: s.link(),
122
+ children: company[l.id]
123
+ }
124
+ ) }, l.id)) })
101
125
  ] })
102
126
  ] })
103
127
  ] }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/site-footer/site-footer.tsx"],"sourcesContent":["// Client (the marks hold an id). The footer shared by every site of the Krizaka family — one calm band (Cahier, ADR-004;\n// peer review krizaka-ui#434: « too much, a double footer »): the site's own columns and the family's columns side by\n// side — Products · Open source (GitHub with them) · Krizaka (our story, the blog, contact) — then one line: the\n// signature (“A Krizaka product”, by the kind of the current site, to www), the version, the place, the legal links.\n// No site block (the bar already names the site), no column that lists only Krizaka, no link twice.\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { FamilyMark } from \"../family-mark\";\nimport { KrizakaLogo } from \"../marks/KrizakaLogo\";\nimport { companyLinks, type FamilyLabels, familyLabels, siteById, type SiteId, sitesByGroup } from \"../sites/sites\";\n\nexport const siteFooter = tv({\n slots: {\n root: \"w-full border-t border-border-subtle bg-surface-0 text-fg\",\n inner:\n \"mx-auto grid w-full max-w-[calc(var(--kz-page-max,72rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] grid-cols-[minmax(0,1fr)] gap-10 px-[var(--kz-page-gutter,clamp(16px,3.2vw,32px))] py-12\",\n band: \"grid grid-cols-[minmax(0,1fr)] gap-8 lg:grid-flow-col lg:auto-cols-[minmax(0,1fr)]\",\n own: \"grid grid-cols-[repeat(auto-fit,minmax(9rem,1fr))] gap-8\",\n family: \"grid grid-cols-2 gap-8 sm:grid-cols-3\",\n column: \"grid min-w-0 content-start gap-3\",\n title: \"text-[11px] font-semibold text-fg-secondary\",\n list: \"grid min-w-0 gap-2\",\n link:\n \"inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=true]:text-fg aria-[current=true]:font-semibold\",\n mark: \"flex h-4 w-4 shrink-0 items-center justify-center text-fg\",\n tag: \"rounded-sm bg-surface-3 px-1.5 py-px text-[10px] font-semibold text-fg-secondary\",\n bottom: \"flex flex-wrap items-center gap-x-5 gap-y-3 border-t border-border-subtle pt-6 text-xs text-fg-secondary\",\n signature:\n \"inline-flex items-center gap-2 rounded-md font-medium text-fg no-underline hover:text-fg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n version:\n \"rounded-sm border border-border-subtle bg-surface-2 px-2 py-0.5 font-mono text-[11px] text-fg-secondary\",\n legal: \"flex flex-wrap items-center gap-x-4 gap-y-2 sm:ml-auto\",\n },\n variants: {\n // `site`: the full footer. `docs`: no site block, the columns in one row, on the documentation's width. `app`: one\n // slim line inside a signed-in product — signature, version, legal links.\n variant: {\n site: {},\n docs: {\n inner: \"max-w-[calc(var(--kz-page-max-docs,88rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] gap-6 py-8\",\n own: \"sm:grid-cols-4\",\n },\n app: {\n root: \"bg-transparent\",\n inner: \"gap-0 py-3\",\n bottom: \"border-t-0 pt-0\",\n },\n },\n },\n defaultVariants: { variant: \"site\" },\n});\n\nexport type SiteFooterProps = Omit<React.ComponentProps<\"footer\">, \"children\"> & {\n /** The site this footer belongs to (`@krizaka/ui/sites`): its mark and line, its signature, marked in the family. */\n current: SiteId;\n /**\n * The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.\n * @default familyLabels.en\n */\n labels?: FamilyLabels;\n /** The site's own columns (`SiteFooter.Column`), before the family. */\n children?: React.ReactNode;\n /** The version the site runs (`1.2.3`, shown `v1.2.3`). */\n version?: string;\n /** The environment, when it is not production (`DEV`). */\n env?: string;\n /**\n * Shows the family in columns (the Krizaka sites: www, ui., java.). A product is independent once deployed: pass\n * `family={false}` and the footer holds only its own columns, the legal links, the version and one publisher line —\n * “A Krizaka product”, linking to www.krizaka.com.\n * @default true\n */\n family?: boolean;\n /** The end of the signature line: legal links, a language switch (`SiteFooter.Link`s or any inline content). */\n legal?: React.ReactNode;\n /**\n * `site` — the full footer of a marketing or company site. `docs` — a compact one for documentation pages (no site\n * block, the columns in a row, the documentation's width; never the family). `app` — one slim line inside a signed-in\n * product: the publisher line, the version and the legal links (no columns, no family); render it once, in the\n * layout, and not at all where the app shell has a sidebar that holds them.\n * @default \"site\"\n */\n variant?: \"site\" | \"docs\" | \"app\";\n};\n\n/** The footer of a Krizaka site, one band: its own columns and the family's, then one line — signature, version, Montréal, legal. */\nexport function SiteFooter({\n current,\n labels = familyLabels.en,\n children,\n version,\n env,\n legal,\n family: familyProp = true,\n variant = \"site\",\n className,\n ...props\n}: SiteFooterProps) {\n const id = React.useId();\n const s = siteFooter({ variant });\n const family = variant === \"site\" && familyProp;\n const slim = variant === \"app\";\n const site = siteById(current);\n const krizaka = siteById(\"krizaka\");\n const tag = [env, version && `v${version.replace(/^v/, \"\")}`].filter(Boolean).join(\" · \");\n const own = React.Children.toArray(children).length > 0;\n const lang = labels.lang ?? \"en\";\n const company = labels.company ?? familyLabels.en.company!;\n // Products · Open source (GitHub, every repository, closes it) · Krizaka (the company's pages): three columns, no\n // column that lists only Krizaka.\n const groups = sitesByGroup();\n const columns = [\n ...groups.filter((g) => g.group === \"products\"),\n { group: \"open-source\" as const, sites: groups.filter((g) => g.group === \"open-source\" || g.group === \"github\").flatMap((g) => g.sites) },\n ];\n return (\n <footer className={s.root({ className })} {...props}>\n <div className={s.inner()}>\n {!slim && (own || family) && (\n <div className={s.band()}>\n {own && <div className={s.own()}>{children}</div>}\n {family && (\n <nav aria-label={labels.family} className={s.family()}>\n {columns.map(({ group, sites }) => (\n <div key={group} className={s.column()}>\n <p id={`${id}-${group}`} className={s.title()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className={s.list()}>\n {sites.map((item) => (\n <li key={item.id}>\n <a href={item.url} aria-current={item.id === current ? \"true\" : undefined} className={s.link()}>\n <span className={s.mark()}>\n <FamilyMark mark={item.mark} size={16} />\n </span>\n {item.name}\n {item.status !== \"released\" && <span className={s.tag()}>{labels.status[item.status]}</span>}\n {item.id === current && <span className=\"sr-only\">({labels.current})</span>}\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n <div className={s.column()}>\n <p id={`${id}-krizaka`} className={s.title()}>\n {labels.groups.krizaka}\n </p>\n <ul aria-labelledby={`${id}-krizaka`} className={s.list()}>\n {companyLinks.map((l) => (\n <li key={l.id}>\n <a href={l.url[lang]} className={s.link()}>\n {company[l.id]}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </nav>\n )}\n </div>\n )}\n <div className={s.bottom()}>\n <a href={krizaka.url} className={s.signature()}>\n <KrizakaLogo size={18} animated={false} />\n {labels.signature[site.kind]}\n </a>\n {tag && (\n <span className={s.version()}>\n <span className=\"sr-only\">{labels.version} </span>\n {tag}\n </span>\n )}\n {!slim && <span>{labels.place}</span>}\n {legal && <div className={s.legal()}>{legal}</div>}\n </div>\n </div>\n </footer>\n );\n}\n\nexport type SiteFooterColumnProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** The column's heading (“Docs”) — passed translated. */\n title: string;\n /** Its links (`SiteFooter.Link`). */\n children: React.ReactNode;\n};\n\n/** One of the site's own columns: a heading and its links. */\nexport function SiteFooterColumn({ title, children, className, ...props }: SiteFooterColumnProps) {\n const id = React.useId();\n // A group with no link is not a column: only a heading over nothing.\n if (React.Children.toArray(children).length === 0) return null;\n const s = siteFooter();\n return (\n <div className={s.column({ className })} {...props}>\n <p id={id} className={s.title()}>\n {title}\n </p>\n <ul aria-labelledby={id} className={s.list()}>\n {React.Children.toArray(children).map((child, i) => <li key={i}>{child}</li>)}\n </ul>\n </div>\n );\n}\n\nexport type SiteFooterLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page: `aria-current=\"page\"`. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the footer. */\nexport function SiteFooterLink({ active, asChild, className, ...props }: SiteFooterLinkProps) {\n const s = siteFooter();\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.link({ className })} {...props} />;\n}\n\nSiteFooter.Column = SiteFooterColumn;\nSiteFooter.Link = SiteFooterLink;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/site-footer/site-footer.tsx"],"sourcesContent":["// Client (the marks hold an id). The footer shared by every site of the Krizaka family — one calm band (Cahier, ADR-004;\n// peer review krizaka-ui#434: « too much, a double footer »): the site's own columns and the family's columns side by\n// side — Products · Open source (GitHub with them) · Krizaka (our story, the blog, contact) — then one line, with no\n// rule above it (a bottom bar under the columns read as a second footer, 2026-10-21): the signature (“A Krizaka product”, by the kind of the current site, to www), the version, the place, the legal links.\n// No site block (the bar already names the site), no column that lists only Krizaka, no link twice.\nimport { Slot } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { FamilyMark } from \"../family-mark\";\nimport { KrizakaLogo } from \"../marks/KrizakaLogo\";\nimport { companyLinks, type FamilyLabels, familyLabels, siteById, type SiteId, sitesByGroup } from \"../sites/sites\";\n\nexport const siteFooter = tv({\n slots: {\n root: \"w-full border-t border-border-subtle bg-surface-0 text-fg\",\n inner:\n \"mx-auto grid w-full max-w-[calc(var(--kz-page-max,72rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] grid-cols-[minmax(0,1fr)] gap-10 px-[var(--kz-page-gutter,clamp(16px,3.2vw,32px))] py-12\",\n band: \"grid grid-cols-[minmax(0,1fr)] gap-8 lg:grid-flow-col lg:auto-cols-[minmax(0,1fr)]\",\n own: \"grid grid-cols-[repeat(auto-fit,minmax(9rem,1fr))] gap-8\",\n family: \"grid grid-cols-2 gap-8 sm:grid-cols-3\",\n column: \"grid min-w-0 content-start gap-3\",\n title: \"text-[11px] font-semibold text-fg-secondary\",\n list: \"grid min-w-0 gap-2\",\n link:\n \"inline-flex min-h-6 min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 rounded-md text-sm [overflow-wrap:anywhere] text-fg-secondary no-underline transition-colors hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-fg aria-[current=page]:font-semibold aria-[current=true]:text-fg aria-[current=true]:font-semibold\",\n mark: \"flex h-4 w-4 shrink-0 items-center justify-center text-fg\",\n tag: \"rounded-sm bg-surface-3 px-1.5 py-px text-[10px] font-semibold text-fg-secondary\",\n bottom: \"flex flex-wrap items-center gap-x-5 gap-y-3 text-xs text-fg-secondary\",\n signature:\n \"inline-flex items-center gap-2 rounded-md font-medium text-fg no-underline hover:text-fg-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n version:\n \"rounded-sm border border-border-subtle bg-surface-2 px-2 py-0.5 font-mono text-[11px] text-fg-secondary\",\n legal: \"flex flex-wrap items-center gap-x-4 gap-y-2 sm:ml-auto\",\n },\n variants: {\n // `site`: the full footer. `docs`: no site block, the columns in one row, on the documentation's width. `app`: one\n // slim line inside a signed-in product — signature, version, legal links.\n variant: {\n site: {},\n docs: {\n inner: \"max-w-[calc(var(--kz-page-max-docs,88rem)_+_2*var(--kz-page-gutter,clamp(16px,3.2vw,32px)))] gap-6 py-8\",\n own: \"sm:grid-cols-4\",\n },\n app: {\n root: \"bg-transparent\",\n inner: \"gap-0 py-3\",\n },\n },\n },\n defaultVariants: { variant: \"site\" },\n});\n\nconst bare = (p: string) => p.replace(/^\\/(en|fr)(?=\\/|$)/, \"\").replace(/\\/+$/, \"\") || \"/\";\n\n/** Is `href` (an absolute family address) the page `path` of the site at `siteUrl`? Locale prefix and trailing slash do not count. */\nfunction isThisPage(href: string, siteUrl: string, path: string): boolean {\n try {\n const target = new URL(href);\n return target.host === new URL(siteUrl).host && bare(target.pathname) === bare(path.split(/[?#]/)[0]!);\n } catch {\n return false;\n }\n}\n\n/** The link to the page you are on: no reload, back to the top (the browser would otherwise keep or restore the scroll). */\nfunction backToTop(event: React.MouseEvent<HTMLAnchorElement>) {\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;\n event.preventDefault();\n window.scrollTo({ top: 0, behavior: \"auto\" });\n}\n\nexport type SiteFooterProps = Omit<React.ComponentProps<\"footer\">, \"children\"> & {\n /** The site this footer belongs to (`@krizaka/ui/sites`): its mark and line, its signature, marked in the family. */\n current: SiteId;\n /**\n * The family's words, passed translated: `familyLabels.fr` from `@krizaka/ui/sites`, or your own of the same shape.\n * @default familyLabels.en\n */\n labels?: FamilyLabels;\n /** The site's own columns (`SiteFooter.Column`), before the family. */\n children?: React.ReactNode;\n /** The version the site runs (`1.2.3`, shown `v1.2.3`). */\n version?: string;\n /** The environment, when it is not production (`DEV`). */\n env?: string;\n /**\n * The path of the page being read on this site (`/en/story`, `/blog/…`): the company link that points to this very\n * page says so (`aria-current=\"page\"`, a visible state) and a click on it scrolls to the top instead of reloading.\n */\n path?: string;\n /**\n * Shows the family in columns (the Krizaka sites: www, ui., java.). A product is independent once deployed: pass\n * `family={false}` and the footer holds only its own columns, the legal links, the version and one publisher line —\n * “A Krizaka product”, linking to www.krizaka.com.\n * @default true\n */\n family?: boolean;\n /** The end of the signature line: legal links, a language switch (`SiteFooter.Link`s or any inline content). */\n legal?: React.ReactNode;\n /**\n * `site` — the full footer of a marketing or company site. `docs` — a compact one for documentation pages (no site\n * block, the columns in a row, the documentation's width; never the family). `app` — one slim line inside a signed-in\n * product: the publisher line, the version and the legal links (no columns, no family); render it once, in the\n * layout, and not at all where the app shell has a sidebar that holds them.\n * @default \"site\"\n */\n variant?: \"site\" | \"docs\" | \"app\";\n};\n\n/** The footer of a Krizaka site, one band: its own columns and the family's, then one line — signature, version, Montréal, legal. */\nexport function SiteFooter({\n current,\n labels = familyLabels.en,\n children,\n version,\n env,\n path,\n legal,\n family: familyProp = true,\n variant = \"site\",\n className,\n ...props\n}: SiteFooterProps) {\n const id = React.useId();\n const s = siteFooter({ variant });\n const family = variant === \"site\" && familyProp;\n const slim = variant === \"app\";\n const site = siteById(current);\n const krizaka = siteById(\"krizaka\");\n const tag = [env, version && `v${version.replace(/^v/, \"\")}`].filter(Boolean).join(\" · \");\n const own = React.Children.toArray(children).length > 0;\n const lang = labels.lang ?? \"en\";\n const company = labels.company ?? familyLabels.en.company!;\n const here = (href: string) => path !== undefined && isThisPage(href, site.url, path);\n // Products · Open source (GitHub, every repository, closes it) · Krizaka (the company's pages): three columns, no\n // column that lists only Krizaka.\n const groups = sitesByGroup();\n const columns = [\n ...groups.filter((g) => g.group === \"products\"),\n { group: \"open-source\" as const, sites: groups.filter((g) => g.group === \"open-source\" || g.group === \"github\").flatMap((g) => g.sites) },\n ];\n return (\n <footer className={s.root({ className })} {...props}>\n <div className={s.inner()}>\n {!slim && (own || family) && (\n <div className={s.band()}>\n {own && <div className={s.own()}>{children}</div>}\n {family && (\n <nav aria-label={labels.family} className={s.family()}>\n {columns.map(({ group, sites }) => (\n <div key={group} className={s.column()}>\n <p id={`${id}-${group}`} className={s.title()}>\n {labels.groups[group]}\n </p>\n <ul aria-labelledby={`${id}-${group}`} className={s.list()}>\n {sites.map((item) => (\n <li key={item.id}>\n <a href={item.url} aria-current={item.id === current ? \"true\" : undefined} className={s.link()}>\n <span className={s.mark()}>\n <FamilyMark mark={item.mark} size={16} />\n </span>\n {item.name}\n {item.status !== \"released\" && <span className={s.tag()}>{labels.status[item.status]}</span>}\n {item.id === current && <span className=\"sr-only\">({labels.current})</span>}\n </a>\n </li>\n ))}\n </ul>\n </div>\n ))}\n <div className={s.column()}>\n <p id={`${id}-krizaka`} className={s.title()}>\n {labels.groups.krizaka}\n </p>\n <ul aria-labelledby={`${id}-krizaka`} className={s.list()}>\n {companyLinks.map((l) => (\n <li key={l.id}>\n <a\n href={l.url[lang]}\n aria-current={here(l.url[lang]) ? \"page\" : undefined}\n onClick={here(l.url[lang]) ? backToTop : undefined}\n className={s.link()}\n >\n {company[l.id]}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </nav>\n )}\n </div>\n )}\n <div className={s.bottom()}>\n <a href={krizaka.url} className={s.signature()}>\n <KrizakaLogo size={18} animated={false} />\n {labels.signature[site.kind]}\n </a>\n {tag && (\n <span className={s.version()}>\n <span className=\"sr-only\">{labels.version} </span>\n {tag}\n </span>\n )}\n {!slim && <span>{labels.place}</span>}\n {legal && <div className={s.legal()}>{legal}</div>}\n </div>\n </div>\n </footer>\n );\n}\n\nexport type SiteFooterColumnProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** The column's heading (“Docs”) — passed translated. */\n title: string;\n /** Its links (`SiteFooter.Link`). */\n children: React.ReactNode;\n};\n\n/** One of the site's own columns: a heading and its links. */\nexport function SiteFooterColumn({ title, children, className, ...props }: SiteFooterColumnProps) {\n const id = React.useId();\n // A group with no link is not a column: only a heading over nothing.\n if (React.Children.toArray(children).length === 0) return null;\n const s = siteFooter();\n return (\n <div className={s.column({ className })} {...props}>\n <p id={id} className={s.title()}>\n {title}\n </p>\n <ul aria-labelledby={id} className={s.list()}>\n {React.Children.toArray(children).map((child, i) => <li key={i}>{child}</li>)}\n </ul>\n </div>\n );\n}\n\nexport type SiteFooterLinkProps = React.ComponentProps<\"a\"> & {\n /** The current page: `aria-current=\"page\"`. */\n active?: boolean;\n /** Renders your router's `<Link>`. */\n asChild?: boolean;\n};\n\n/** A link of the footer. */\nexport function SiteFooterLink({ active, asChild, className, ...props }: SiteFooterLinkProps) {\n const s = siteFooter();\n const Comp = asChild ? Slot.Root : \"a\";\n return <Comp aria-current={active ? \"page\" : undefined} className={s.link({ className })} {...props} />;\n}\n\nSiteFooter.Column = SiteFooterColumn;\nSiteFooter.Link = SiteFooterLink;\n"],"mappings":";;;;;;;;;;;;;AAKA,SAAS,YAAY;AACrB,YAAY,WAAW;AACvB,SAAS,UAAU;AA6IC,cAiBgC,YAjBhC;AAvIb,IAAM,aAAa,GAAG;AAAA,EAC3B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,OACE;AAAA,IACF,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MACE;AAAA,IAEF,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,WACE;AAAA,IACF,SACE;AAAA,IACF,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA;AAAA;AAAA,IAGR,SAAS;AAAA,MACP,MAAM,CAAC;AAAA,MACP,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,KAAK;AAAA,MACP;AAAA,MACA,KAAK;AAAA,QACH,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,OAAO;AACrC,CAAC;AAED,IAAM,OAAO,CAAC,MAAc,EAAE,QAAQ,sBAAsB,EAAE,EAAE,QAAQ,QAAQ,EAAE,KAAK;AAGvF,SAAS,WAAW,MAAc,SAAiB,MAAuB;AACxE,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,IAAI;AAC3B,WAAO,OAAO,SAAS,IAAI,IAAI,OAAO,EAAE,QAAQ,KAAK,OAAO,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,EAAE,CAAC,CAAE;AAAA,EACvG,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,UAAU,OAA4C;AAC7D,MAAI,MAAM,WAAW,MAAM,WAAW,MAAM,YAAY,MAAM,WAAW,EAAG;AAC5E,QAAM,eAAe;AACrB,SAAO,SAAS,EAAE,KAAK,GAAG,UAAU,OAAO,CAAC;AAC9C;AAyCO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,SAAS,aAAa;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ,aAAa;AAAA,EACrB,UAAU;AAAA,EACV;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,QAAM,KAAW,YAAM;AACvB,QAAM,IAAI,WAAW,EAAE,QAAQ,CAAC;AAChC,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,OAAO,YAAY;AACzB,QAAM,OAAO,SAAS,OAAO;AAC7B,QAAM,UAAU,SAAS,SAAS;AAClC,QAAM,MAAM,CAAC,KAAK,WAAW,IAAI,QAAQ,QAAQ,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK;AACxF,QAAM,MAAY,eAAS,QAAQ,QAAQ,EAAE,SAAS;AACtD,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,UAAU,OAAO,WAAW,aAAa,GAAG;AAClD,QAAM,OAAO,CAAC,SAAiB,SAAS,UAAa,WAAW,MAAM,KAAK,KAAK,IAAI;AAGpF,QAAM,SAAS,aAAa;AAC5B,QAAM,UAAU;AAAA,IACd,GAAG,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,UAAU;AAAA,IAC9C,EAAE,OAAO,eAAwB,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,iBAAiB,EAAE,UAAU,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE;AAAA,EAC1I;AACA,SACE,oBAAC,YAAO,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC5C,+BAAC,SAAI,WAAW,EAAE,MAAM,GACrB;AAAA,KAAC,SAAS,OAAO,WAChB,qBAAC,SAAI,WAAW,EAAE,KAAK,GACpB;AAAA,aAAO,oBAAC,SAAI,WAAW,EAAE,IAAI,GAAI,UAAS;AAAA,MAC1C,UACC,qBAAC,SAAI,cAAY,OAAO,QAAQ,WAAW,EAAE,OAAO,GACjD;AAAA,gBAAQ,IAAI,CAAC,EAAE,OAAO,MAAM,MAC3B,qBAAC,SAAgB,WAAW,EAAE,OAAO,GACnC;AAAA,8BAAC,OAAE,IAAI,GAAG,EAAE,IAAI,KAAK,IAAI,WAAW,EAAE,MAAM,GACzC,iBAAO,OAAO,KAAK,GACtB;AAAA,UACA,oBAAC,QAAG,mBAAiB,GAAG,EAAE,IAAI,KAAK,IAAI,WAAW,EAAE,KAAK,GACtD,gBAAM,IAAI,CAAC,SACV,oBAAC,QACC,+BAAC,OAAE,MAAM,KAAK,KAAK,gBAAc,KAAK,OAAO,UAAU,SAAS,QAAW,WAAW,EAAE,KAAK,GAC3F;AAAA,gCAAC,UAAK,WAAW,EAAE,KAAK,GACtB,8BAAC,cAAW,MAAM,KAAK,MAAM,MAAM,IAAI,GACzC;AAAA,YACC,KAAK;AAAA,YACL,KAAK,WAAW,cAAc,oBAAC,UAAK,WAAW,EAAE,IAAI,GAAI,iBAAO,OAAO,KAAK,MAAM,GAAE;AAAA,YACpF,KAAK,OAAO,WAAW,qBAAC,UAAK,WAAU,WAAU;AAAA;AAAA,cAAE,OAAO;AAAA,cAAQ;AAAA,eAAC;AAAA,aACtE,KARO,KAAK,EASd,CACD,GACH;AAAA,aAjBQ,KAkBV,CACD;AAAA,QACD,qBAAC,SAAI,WAAW,EAAE,OAAO,GACvB;AAAA,8BAAC,OAAE,IAAI,GAAG,EAAE,YAAY,WAAW,EAAE,MAAM,GACxC,iBAAO,OAAO,SACjB;AAAA,UACA,oBAAC,QAAG,mBAAiB,GAAG,EAAE,YAAY,WAAW,EAAE,KAAK,GACrD,uBAAa,IAAI,CAAC,MACjB,oBAAC,QACC;AAAA,YAAC;AAAA;AAAA,cACC,MAAM,EAAE,IAAI,IAAI;AAAA,cAChB,gBAAc,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,SAAS;AAAA,cAC3C,SAAS,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,YAAY;AAAA,cACzC,WAAW,EAAE,KAAK;AAAA,cAEjB,kBAAQ,EAAE,EAAE;AAAA;AAAA,UACf,KARO,EAAE,EASX,CACD,GACH;AAAA,WACF;AAAA,SACF;AAAA,OAEJ;AAAA,IAEF,qBAAC,SAAI,WAAW,EAAE,OAAO,GACvB;AAAA,2BAAC,OAAE,MAAM,QAAQ,KAAK,WAAW,EAAE,UAAU,GAC3C;AAAA,4BAAC,eAAY,MAAM,IAAI,UAAU,OAAO;AAAA,QACvC,OAAO,UAAU,KAAK,IAAI;AAAA,SAC7B;AAAA,MACC,OACC,qBAAC,UAAK,WAAW,EAAE,QAAQ,GACzB;AAAA,6BAAC,UAAK,WAAU,WAAW;AAAA,iBAAO;AAAA,UAAQ;AAAA,WAAC;AAAA,QAC1C;AAAA,SACH;AAAA,MAED,CAAC,QAAQ,oBAAC,UAAM,iBAAO,OAAM;AAAA,MAC7B,SAAS,oBAAC,SAAI,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,OAC9C;AAAA,KACF,GACF;AAEJ;AAUO,SAAS,iBAAiB,EAAE,OAAO,UAAU,WAAW,GAAG,MAAM,GAA0B;AAChG,QAAM,KAAW,YAAM;AAEvB,MAAU,eAAS,QAAQ,QAAQ,EAAE,WAAW,EAAG,QAAO;AAC1D,QAAM,IAAI,WAAW;AACrB,SACE,qBAAC,SAAI,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,GAAI,GAAG,OAC3C;AAAA,wBAAC,OAAE,IAAQ,WAAW,EAAE,MAAM,GAC3B,iBACH;AAAA,IACA,oBAAC,QAAG,mBAAiB,IAAI,WAAW,EAAE,KAAK,GACxC,UAAM,eAAS,QAAQ,QAAQ,EAAE,IAAI,CAAC,OAAO,MAAM,oBAAC,QAAY,mBAAJ,CAAU,CAAK,GAC9E;AAAA,KACF;AAEJ;AAUO,SAAS,eAAe,EAAE,QAAQ,SAAS,WAAW,GAAG,MAAM,GAAwB;AAC5F,QAAM,IAAI,WAAW;AACrB,QAAM,OAAO,UAAU,KAAK,OAAO;AACnC,SAAO,oBAAC,QAAK,gBAAc,SAAS,SAAS,QAAW,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACvG;AAEA,WAAW,SAAS;AACpB,WAAW,OAAO;","names":[]}
package/dist/sites.js CHANGED
@@ -2,13 +2,13 @@
2
2
  var site = (s) => ({ ...s, host: s.url.replace(/^https?:\/\//, "").replace(/\/$/, "") });
3
3
  var sites = [
4
4
  site({ id: "krizaka", name: "Krizaka", url: "https://www.krizaka.com", kind: "company", group: "krizaka", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-com" }),
5
- site({ id: "orazaka", name: "Orazaka", url: "https://dev.orazaka.com", kind: "product", group: "products", status: "released", mark: "orazaka", repo: "https://github.com/krizaka/orazaka" }),
6
- site({ id: "orochia", name: "Orochia", url: "https://dev.orochia.com", kind: "product", group: "products", status: "released", mark: "orochia", repo: "https://github.com/krizaka/orochia" }),
7
- site({ id: "yasakia", name: "Yasakia", url: "https://dev.yasakia.com", kind: "product", group: "products", status: "development", mark: "yasakia", repo: "https://github.com/krizaka/yasakia" }),
8
- site({ id: "yororis", name: "Yororis", url: "https://dev.yororis.com", kind: "product", group: "products", status: "construction", mark: "yororis", repo: "https://github.com/krizaka/yororis" }),
9
- site({ id: "yomizaka", name: "Yomizaka", url: "https://dev.yomizaka.com", kind: "product", group: "products", status: "development", mark: "yomizaka", repo: "https://github.com/krizaka/yomizaka" }),
10
- site({ id: "kachizaka", name: "Kachizaka", url: "https://dev.kachizaka.com", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
11
- site({ id: "akinaza", name: "Akinaza", url: "https://dev.akinaza.com", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
5
+ site({ id: "orazaka", name: "Orazaka", url: "https://www.orazaka.com", kind: "product", group: "products", status: "released", mark: "orazaka", repo: "https://github.com/krizaka/orazaka" }),
6
+ site({ id: "orochia", name: "Orochia", url: "https://www.orochia.com", kind: "product", group: "products", status: "released", mark: "orochia", repo: "https://github.com/krizaka/orochia" }),
7
+ site({ id: "yasakia", name: "Yasakia", url: "https://www.yasakia.com", kind: "product", group: "products", status: "development", mark: "yasakia", repo: "https://github.com/krizaka/yasakia" }),
8
+ site({ id: "yororis", name: "Yororis", url: "https://www.yororis.com", kind: "product", group: "products", status: "development", mark: "yororis", repo: "https://github.com/krizaka/yororis" }),
9
+ site({ id: "yomizaka", name: "Yomizaka", url: "https://www.yomizaka.com", kind: "product", group: "products", status: "development", mark: "yomizaka", repo: "https://github.com/krizaka/yomizaka" }),
10
+ site({ id: "kachizaka", name: "Kachizaka", url: "https://www.kachizaka.com", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
11
+ site({ id: "akinaza", name: "Akinaza", url: "https://www.akinaza.com", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
12
12
  site({ id: "ui", name: "Krizaka UI", url: "https://ui.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ui" }),
13
13
  site({ id: "java", name: "Krizaka Java", url: "https://java.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-build" }),
14
14
  // The motion lab: built in the open on GitHub Pages; what proves itself there moves into Krizaka UI.
package/dist/sites.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sites/sites.ts"],"sourcesContent":["// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"motion\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing offered (a QA-only app may run; the public page says so). `development`: being built in the\n * open, with a dev site (said \"In development\"). A site with none yet would use its repository as its address.\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://dev.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://dev.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://dev.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://dev.yororis.com\", kind: \"product\", group: \"products\", status: \"construction\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://dev.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://dev.kachizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://dev.akinaza.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n // The motion lab: built in the open on GitHub Pages; what proves itself there moves into Krizaka UI.\n site({ id: \"motion\", name: \"Krizaka Motion\", url: \"https://krizaka.github.io/krizaka-motion\", kind: \"open-source\", group: \"open-source\", status: \"development\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-motion\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The company's own pages, the footer's « Krizaka » column (the brand's home is the signature line's link). */\nexport type CompanyLinkId = \"story\" | \"blog\" | \"contact\";\nexport const companyLinks: readonly { id: CompanyLinkId; url: Record<SiteLocale, string> }[] = [\n { id: \"story\", url: { en: \"https://www.krizaka.com/story\", fr: \"https://www.krizaka.com/fr/story\" } },\n { id: \"blog\", url: { en: \"https://blog.krizaka.com\", fr: \"https://blog.krizaka.com\" } },\n { id: \"contact\", url: { en: \"https://www.krizaka.com/contact\", fr: \"https://www.krizaka.com/fr/contact\" } },\n];\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n /** The language of these words: the company links open in it. @default \"en\" */\n lang?: SiteLocale;\n /** The company's pages in the footer's « Krizaka » column. @default the English words */\n company?: Record<CompanyLinkId, string>;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI on your own servers: chat, documents, images and video — and the engine under the other products.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"Meet real people: introductions, and photos checked before you see them.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n motion: \"The motion lab: the kit's motion, played live with its knobs.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n lang: \"en\",\n company: { story: \"Our story\", blog: \"Blog\", contact: \"Contact us\" },\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine sur vos propres serveurs : conversation, documents, images et vidéo — et le moteur des autres produits.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"Rencontrez de vraies personnes : des présentations, et des photos vérifiées avant que vous les voyiez.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n motion: \"Le labo du mouvement : le mouvement du kit, joué en direct, avec ses réglages.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n lang: \"fr\",\n company: { story: \"Notre histoire\", blog: \"Blogue\", contact: \"Nous écrire\" },\n },\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/sites/sites.ts"],"sourcesContent":["// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"motion\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing offered (a QA-only app may run; the public page says so). `development`: being built in the\n * open, with a dev site (said \"In development\"). A site with none yet would use its repository as its address.\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://www.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://www.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://www.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://www.yororis.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://www.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://www.kachizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://www.akinaza.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n // The motion lab: built in the open on GitHub Pages; what proves itself there moves into Krizaka UI.\n site({ id: \"motion\", name: \"Krizaka Motion\", url: \"https://krizaka.github.io/krizaka-motion\", kind: \"open-source\", group: \"open-source\", status: \"development\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-motion\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The company's own pages, the footer's « Krizaka » column (the brand's home is the signature line's link). */\nexport type CompanyLinkId = \"story\" | \"blog\" | \"contact\";\nexport const companyLinks: readonly { id: CompanyLinkId; url: Record<SiteLocale, string> }[] = [\n { id: \"story\", url: { en: \"https://www.krizaka.com/story\", fr: \"https://www.krizaka.com/fr/story\" } },\n { id: \"blog\", url: { en: \"https://blog.krizaka.com\", fr: \"https://blog.krizaka.com\" } },\n { id: \"contact\", url: { en: \"https://www.krizaka.com/contact\", fr: \"https://www.krizaka.com/fr/contact\" } },\n];\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n /** The language of these words: the company links open in it. @default \"en\" */\n lang?: SiteLocale;\n /** The company's pages in the footer's « Krizaka » column. @default the English words */\n company?: Record<CompanyLinkId, string>;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI on your own servers: chat, documents, images and video — and the engine under the other products.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"Meet real people: introductions, and photos checked before you see them.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n motion: \"The motion lab: the kit's motion, played live with its knobs.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n lang: \"en\",\n company: { story: \"Our story\", blog: \"Blog\", contact: \"Contact us\" },\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine sur vos propres serveurs : conversation, documents, images et vidéo — et le moteur des autres produits.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"Rencontrez de vraies personnes : des présentations, et des photos vérifiées avant que vous les voyiez.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n motion: \"Le labo du mouvement : le mouvement du kit, joué en direct, avec ses réglages.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n lang: \"fr\",\n company: { story: \"Notre histoire\", blog: \"Blogue\", contact: \"Nous écrire\" },\n },\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krizaka/ui",
3
- "version": "3.41.0",
3
+ "version": "3.42.0",
4
4
  "description": "The Krizaka front-end platform's components: the primitives (button, card, dialog, toast, menu, field, tabs, chip, switch, slider, command palette, theme, countdown…) on the semantic --kz-* tokens, the animated marks (Krizaka, Orazaka, Orochia, Yasakia, Yororis) and the motion signature — web and /native.",
5
5
  "keywords": [
6
6
  "krizaka",
@@ -745,7 +745,7 @@
745
745
  ],
746
746
  "peerDependencies": {
747
747
  "@krizaka/query": ">=0.2.1",
748
- "@krizaka/tailwind": ">=3.41.0",
748
+ "@krizaka/tailwind": ">=3.42.0",
749
749
  "@maplibre/maplibre-react-native": ">=11",
750
750
  "@shopify/flash-list": ">=2",
751
751
  "expo-camera": ">=16",
@@ -798,14 +798,14 @@
798
798
  "react-native-svg": "^15.15.4",
799
799
  "react-native-web": "0.21.2",
800
800
  "size-limit": "^14.2.0",
801
- "storybook": "10.6.1",
801
+ "storybook": "10.6.2",
802
802
  "tailwindcss": "^4.3.3",
803
803
  "test-renderer": "^1.3.0",
804
804
  "tsup": "^8.5.1",
805
805
  "typescript": "^5.9.0",
806
806
  "vitest": "^4.1.11",
807
807
  "zod": "^4.6.5",
808
- "@krizaka/config": "0.4.1",
808
+ "@krizaka/config": "0.4.2",
809
809
  "@krizaka/query": "0.2.1"
810
810
  },
811
811
  "engines": {
@@ -1950,7 +1950,7 @@
1950
1950
  {
1951
1951
  "name": "./flock",
1952
1952
  "path": "dist/flock.js",
1953
- "limit": "9 kB",
1953
+ "limit": "10.5 kB",
1954
1954
  "gzip": true,
1955
1955
  "ignore": [
1956
1956
  "tailwind-variants",
@@ -2550,7 +2550,7 @@
2550
2550
  "tailwind-variants": "^3.3.1",
2551
2551
  "@krizaka/intl": "^0.2.1",
2552
2552
  "@krizaka/pacer": "^0.1.0",
2553
- "@krizaka/tokens": "^3.41.0"
2553
+ "@krizaka/tokens": "^3.42.0"
2554
2554
  },
2555
2555
  "scripts": {
2556
2556
  "build": "node -e \"const fs=require('node:fs');fs.rmSync('dist',{recursive:true,force:true});for(const f of fs.readdirSync('registry/examples',{recursive:true}))if(/\\.(js|d\\.ts)$/.test(f))fs.rmSync('registry/examples/'+f)\" && tsup && node -e \"require('node:fs').copyFileSync('src/motion.css','dist/motion.css');require('node:fs').copyFileSync('src/blocks.css','dist/blocks.css');require('node:fs').copyFileSync('src/story.css','dist/story.css')\" && node scripts/build-registry.mjs",