@kolkrabbi/kol-component 0.6.0 → 0.8.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 (38) hide show
  1. package/README.md +8 -0
  2. package/package.json +2 -3
  3. package/src/atoms/RotaryDial.jsx +35 -21
  4. package/src/index.js +6 -18
  5. package/src/molecules/ButtonGroup.jsx +45 -0
  6. package/src/molecules/ColorInputRow.jsx +146 -126
  7. package/src/molecules/Slider.jsx +29 -14
  8. package/src/molecules/SplitToolButton.jsx +133 -0
  9. package/src/organisms/ContentFilters.jsx +2 -2
  10. package/src/organisms/GalleryCarousel.jsx +2 -1
  11. package/src/organisms/LoaderOverlay.jsx +11 -14
  12. package/src/organisms/MediaTileGallery.jsx +57 -0
  13. package/src/organisms/MediaViewer.jsx +89 -64
  14. package/src/atoms/PriceDisplay.jsx +0 -34
  15. package/src/atoms/TextPressure.jsx +0 -331
  16. package/src/atoms/TypeSample.jsx +0 -50
  17. package/src/atoms/TypeSpecCard.jsx +0 -42
  18. package/src/molecules/ArticleCard.jsx +0 -178
  19. package/src/molecules/WorkListItem.jsx +0 -83
  20. package/src/molecules/foundry/SpecimenSectionHeader.jsx +0 -89
  21. package/src/organisms/ArticleHeader.jsx +0 -95
  22. package/src/organisms/ColorLoader.jsx +0 -155
  23. package/src/organisms/DiagonalMarqueeRiver.jsx +0 -138
  24. package/src/organisms/ParallaxShelf.jsx +0 -141
  25. package/src/organisms/PortableTextRenderer.jsx +0 -115
  26. package/src/organisms/ProductDetailLayout.jsx +0 -189
  27. package/src/organisms/ScrollDriftGallery.jsx +0 -214
  28. package/src/organisms/StackHero.jsx +0 -83
  29. package/src/organisms/WorkCard.jsx +0 -120
  30. package/src/organisms/WorkViewToggle.jsx +0 -170
  31. package/src/organisms/foundry/FontPreviewSection.jsx +0 -187
  32. package/src/organisms/foundry/FoundryCharacterSets.jsx +0 -113
  33. package/src/organisms/foundry/GlyphMetricsGrid.jsx +0 -335
  34. package/src/organisms/foundry/TypefaceHero.jsx +0 -107
  35. package/src/organisms/foundry/TypefaceStyleSection.jsx +0 -163
  36. package/src/organisms/foundry/VariableFontSection.jsx +0 -158
  37. package/src/organisms/foundry/glyphData.js +0 -30
  38. package/src/organisms/foundry/index.js +0 -21
@@ -1,158 +0,0 @@
1
- import { useState } from 'react'
2
- import Pill from '../../atoms/Pill.jsx'
3
- import Slider from '../../molecules/Slider.jsx'
4
- import SpecimenSectionHeader from '../../molecules/foundry/SpecimenSectionHeader.jsx'
5
- import useAxisAnimation from '../../hooks/useAxisAnimation.js'
6
-
7
- /* taxonomy-ok: organism — nests Pill, Slider, SpecimenSectionHeader (relative
8
- * imports) plus a same-file PlayPauseButton; owns the axis-animation state. */
9
-
10
- /**
11
- * PlayPauseButton (same-file) — CSS-shape play/pause toggle. Two bars when
12
- * playing, a right-pointing triangle when paused. Pure `currentColor` shapes so
13
- * it needs no icon registry and inherits the surrounding text color.
14
- */
15
- function PlayPauseButton({ isPlaying = false, onToggle, size = 28 }) {
16
- const barH = Math.round(size * 0.43)
17
- const barW = Math.max(2, Math.round(size * 0.07))
18
- const tri = Math.round(size * 0.21)
19
- const gap = Math.max(2, Math.round(size * 0.07))
20
- return (
21
- <button
22
- type="button"
23
- onClick={onToggle}
24
- aria-label={isPlaying ? 'Pause' : 'Play'}
25
- aria-pressed={isPlaying}
26
- className="cursor-pointer flex items-center justify-center text-auto shrink-0"
27
- style={{ width: size, height: size, gap }}
28
- >
29
- {isPlaying ? (
30
- <>
31
- <span className="bg-current" style={{ width: barW, height: barH }} />
32
- <span className="bg-current" style={{ width: barW, height: barH }} />
33
- </>
34
- ) : (
35
- <span
36
- className="w-0 h-0"
37
- style={{
38
- borderLeft: `${tri}px solid currentColor`,
39
- borderTop: `${tri}px solid transparent`,
40
- borderBottom: `${tri}px solid transparent`,
41
- marginLeft: Math.round(size * 0.07),
42
- }}
43
- />
44
- )}
45
- </button>
46
- )
47
- }
48
-
49
- /**
50
- * VariableFontSection — the animated variable-axis playground. A big specimen
51
- * word whose weight auto-oscillates between `minWeight` and `maxWeight` via
52
- * `useAxisAnimation` (ping-pong rAF, reduced-motion gated), pausing the instant
53
- * the user scrubs the weight slider. A SpecimenSectionHeader sits above with a
54
- * Roman/Italic dropdown. "Watch the weight breathe, then grab the slider."
55
- *
56
- * The weight is applied as CSS `font-weight` (→ the font's wght axis), so it
57
- * animates against ANY font with multiple weights — a true variable font makes
58
- * the morph continuous rather than stepped. See the page's FONT-ASSET CONTRACT.
59
- *
60
- * Reconciliations vs the monorepo source: the crude `Date.now()`/`delta>16`
61
- * throttle is replaced by the hook's `performance.now()` accumulator; the
62
- * previously unguarded loop now honors `prefers-reduced-motion` (starts paused,
63
- * static value); brand copy defaults ('Málrómur Aa' / 'Variable' / TGMalromur)
64
- * are dropped for neutral defaults.
65
- *
66
- * Text casing: badgeText, text and dropdown labels render verbatim.
67
- *
68
- * @param {Object} props
69
- * @param {string} props.fontFamily - Specimen family (default system stack).
70
- * @param {string} props.badgeText - Header title (default 'Variable axis').
71
- * @param {string} props.text - The big specimen word (default 'Variable').
72
- * @param {number} props.minWeight - Oscillation + slider lower bound (default 300).
73
- * @param {number} props.maxWeight - Oscillation + slider upper bound (default 900).
74
- * @param {boolean} props.showDropdown - Show the Roman/Italic dropdown (default true).
75
- */
76
- const VariableFontSection = ({
77
- fontFamily = 'system-ui, sans-serif',
78
- badgeText = 'Variable axis',
79
- text = 'Variable',
80
- minWeight = 300,
81
- maxWeight = 900,
82
- showDropdown = true,
83
- }) => {
84
- const [isAnimating, setIsAnimating] = useState(true)
85
- const [selectedStyle, setSelectedStyle] = useState(showDropdown ? 'italic' : 'roman')
86
-
87
- const { value: weight, setValue: setWeight, reduced } = useAxisAnimation({
88
- min: minWeight,
89
- max: maxWeight,
90
- running: isAnimating,
91
- initial: 400,
92
- })
93
-
94
- const handleSliderChange = (value) => {
95
- setIsAnimating(false)
96
- setWeight(value)
97
- }
98
-
99
- const playing = isAnimating && !reduced
100
- const fontStyle = selectedStyle === 'italic' ? 'italic' : 'normal'
101
-
102
- return (
103
- <section className="w-full py-12 lg:py-16">
104
- <div className="max-w-[1400px] mx-auto flex flex-col gap-8">
105
- <SpecimenSectionHeader
106
- selectedStyle={selectedStyle}
107
- onStyleChange={setSelectedStyle}
108
- showDropdown={showDropdown}
109
- badgeText={badgeText}
110
- icon="foundation"
111
- size="sm"
112
- />
113
-
114
- {/* VariableFontDisplay (inlined) — giant text behind, controls in front */}
115
- <div className="relative w-full rounded border border-fg-16 bg-surface-primary overflow-hidden p-6 md:p-10 h-[40vh] md:h-[60vh]">
116
- <p
117
- className="absolute inset-0 flex items-center justify-center text-[80px] md:text-[144px] transition-colors duration-300"
118
- style={{
119
- fontFamily,
120
- fontWeight: Math.round(weight),
121
- fontStyle,
122
- color: 'var(--kol-surface-on-primary)',
123
- }}
124
- >
125
- {text}
126
- </p>
127
-
128
- <div className="relative z-10 h-full flex flex-col justify-between">
129
- <div className="flex justify-between items-start">
130
- <div className="flex flex-col gap-1">
131
- <span className="kol-mono-10 text-fg-32">AXES:</span>
132
- <span className="kol-helper-12 text-auto">WEIGHT</span>
133
- </div>
134
- <div className="flex gap-2">
135
- <Pill variant="subtle">wght {Math.round(weight)}</Pill>
136
- </div>
137
- </div>
138
-
139
- <div className="flex items-center gap-4">
140
- <PlayPauseButton isPlaying={playing} onToggle={() => setIsAnimating((a) => !a)} />
141
- <Slider
142
- label="Weight"
143
- min={minWeight}
144
- max={maxWeight}
145
- value={Math.round(weight)}
146
- onChange={handleSliderChange}
147
- variant="minimal"
148
- className="w-full"
149
- />
150
- </div>
151
- </div>
152
- </div>
153
- </div>
154
- </section>
155
- )
156
- }
157
-
158
- export default VariableFontSection
@@ -1,30 +0,0 @@
1
- /**
2
- * Foundry glyph data — static character collections + category metadata for the
3
- * type-specimen sections (GlyphMetricsGrid, FoundryCharacterSets). Ported from
4
- * the monorepo `@kol/ui/data` glyphSets so the DS foundry layer carries its own
5
- * default coverage instead of reaching into an app data package. Consumers can
6
- * override any of it via the `uppercaseGlyphs` / `lowercaseGlyphs` / category
7
- * props.
8
- */
9
-
10
- export const glyphSets = {
11
- uppercase: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
12
- lowercase: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],
13
- numbers: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
14
- punctuation: ['.', ',', '!', '?', ';', ':', '"', "'", '-', '—', '(', ')', '[', ']', '{', '}', '&', '@', '#', '$', '%'],
15
- latin1: ['À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø'],
16
- latinExtended: ['Ā', 'Ă', 'Ą', 'Ć', 'Ĉ', 'Ċ', 'Č', 'Ď', 'Đ', 'Ē', 'Ĕ', 'Ė', 'Ę', 'Ě', 'Ĝ', 'Ğ', 'Ġ', 'Ģ', 'Ĥ', 'Ħ', 'Ĩ', 'Ī', 'Ĭ', 'Į'],
17
- }
18
-
19
- export const glyphCategories = [
20
- { key: 'uppercase', title: 'Uppercase' },
21
- { key: 'lowercase', title: 'Lowercase' },
22
- { key: 'numbers', title: 'Numbers' },
23
- { key: 'punctuation', title: 'Punctuation & Symbols' },
24
- { key: 'latin1', title: 'Latin-1 Supported' },
25
- { key: 'latinExtended', title: 'Latin Extended' },
26
- ]
27
-
28
- /** Default preview pangram — neutral English, authored in intended case. */
29
- export const SPECIMEN_SAMPLE_TEXT =
30
- 'The quick brown fox jumps over the lazy dog while five wizards vex the gnomic judge.'
@@ -1,21 +0,0 @@
1
- /**
2
- * @kol/component foundry sub-barrel — the type-specimen layer (the DS answer to
3
- * the monorepo's `@kol/ui/foundry`). Exposed as the `./foundry` package subpath
4
- * so the showcase specimen set can import these without touching the root
5
- * src/index.js barrel. The root barrel export lines are documented in the p9
6
- * wiring notes for a central merge.
7
- */
8
-
9
- // molecule (shared section header)
10
- export { default as SpecimenSectionHeader } from '../../molecules/foundry/SpecimenSectionHeader.jsx'
11
-
12
- // organisms (specimen sections)
13
- export { default as TypefaceHero } from './TypefaceHero.jsx'
14
- export { default as VariableFontSection } from './VariableFontSection.jsx'
15
- export { default as GlyphMetricsGrid } from './GlyphMetricsGrid.jsx'
16
- export { default as TypefaceStyleSection } from './TypefaceStyleSection.jsx'
17
- export { default as FontPreviewSection } from './FontPreviewSection.jsx'
18
- export { default as FoundryCharacterSets } from './FoundryCharacterSets.jsx'
19
-
20
- // data
21
- export { glyphSets, glyphCategories, SPECIMEN_SAMPLE_TEXT } from './glyphData.js'