@sigx/lynx-daisyui 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -66,3 +66,4 @@ export { Text } from './typography/Text.js';
66
66
  export type { TextProps, TextSize, TextWeight, TextColor } from './typography/Text.js';
67
67
  export { Heading } from './typography/Heading.js';
68
68
  export type { HeadingProps, HeadingLevel } from './typography/Heading.js';
69
+ export { markdownComponents } from './markdown/components.js';
package/dist/index.js CHANGED
@@ -46,3 +46,5 @@ export { Avatar } from './data/Avatar.js';
46
46
  // Typography
47
47
  export { Text } from './typography/Text.js';
48
48
  export { Heading } from './typography/Heading.js';
49
+ // Markdown — daisyUI rendering for `@sigx/lynx-markdown` (optional peer).
50
+ export { markdownComponents } from './markdown/components.js';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * daisyUI rendering for `@sigx/lynx-markdown`.
3
+ *
4
+ * `@sigx/lynx-markdown` is design-system-agnostic: `<MarkdownView>` walks the
5
+ * markdown AST and calls a {@link MarkdownComponents} render function per node
6
+ * type. This module supplies the daisyUI mapping — headings → `<Heading>`, text
7
+ * → `<Text>`, layout → `<Col>`/`<Row>`, themed surfaces/borders via daisyUI
8
+ * utility classes — so markdown output matches the rest of the design system and
9
+ * follows the active theme.
10
+ *
11
+ * The class literals live here in `@sigx/lynx-daisyui/src`, so the app's Tailwind
12
+ * `content` glob (which already scans this package) generates them; and daisyUI's
13
+ * `<Col>`/`<Row>` set `display:flex`, so layout is correct on Lynx.
14
+ *
15
+ * `@sigx/lynx-markdown` is an *optional* peer dependency — importing daisyUI
16
+ * without it is fine; you just don't use `markdownComponents`.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * import { MarkdownView } from '@sigx/lynx-markdown';
21
+ * import { markdownComponents } from '@sigx/lynx-daisyui';
22
+ *
23
+ * <MarkdownView value={md} components={markdownComponents} onLink={open} />
24
+ * ```
25
+ */
26
+ import type { MarkdownComponents } from '@sigx/lynx-markdown';
27
+ export declare const markdownComponents: MarkdownComponents;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@sigx/lynx/jsx-runtime";
2
+ import { Heading } from '../typography/Heading.js';
3
+ import { Text } from '../typography/Text.js';
4
+ import { Col } from '../layout/Col.js';
5
+ import { Row } from '../layout/Row.js';
6
+ import { Divider } from '../layout/Divider.js';
7
+ import { Checkbox } from '../forms/Checkbox.js';
8
+ function alignClass(align) {
9
+ return align === 'center' ? 'text-center' : align === 'right' ? 'text-right' : 'text-left';
10
+ }
11
+ export const markdownComponents = {
12
+ root: ({ children }) => _jsx(Col, { gap: 12, children: children }),
13
+ heading: ({ level, children }) => _jsx(Heading, { level: level, children: children }),
14
+ paragraph: ({ children }) => _jsx(Text, { class: "leading-relaxed", children: children }),
15
+ blockquote: ({ children }) => (_jsx(Col, { gap: 8, class: "border-l-4 border-base-300 pl-4 opacity-80", children: children })),
16
+ list: ({ children }) => _jsx(Col, { gap: 4, children: children }),
17
+ listItem: ({ ordered, number, checked, children }) => (_jsxs(Row, { gap: 6, align: "flex-start", children: [checked !== null ? (_jsx(Checkbox, { checked: checked, size: "sm", disabled: true, class: "mt-1" })) : ordered ? (_jsx(Text, { class: "opacity-60 leading-relaxed", children: `${number}.` })) : (_jsx("view", { style: {
18
+ width: 6,
19
+ height: 6,
20
+ borderRadius: 3,
21
+ marginTop: 11,
22
+ backgroundColor: 'rgba(127, 127, 127, 0.9)',
23
+ } })), _jsx(Col, { gap: 4, class: "flex-1", children: children })] })),
24
+ code: ({ lang, value }) => (_jsxs(Col, { gap: 4, background: "base-200", borderRadius: 8, padding: 12, children: [lang ? _jsx(Text, { size: "xs", class: "opacity-60 font-mono", children: lang }) : null, _jsx(Text, { size: "sm", class: "font-mono whitespace-pre-wrap", children: value })] })),
25
+ thematicBreak: () => _jsx(Divider, {}),
26
+ table: ({ children }) => (_jsx(Col, { class: "border border-base-300 rounded-lg overflow-hidden", children: children })),
27
+ tableRow: ({ header, children }) => (_jsx(Row, { class: header ? 'bg-base-200' : '', children: children })),
28
+ tableCell: ({ header, align, children }) => (_jsx("view", { class: "flex-1 px-2 py-1 border-b border-base-300", children: _jsx(Text, { size: "sm", weight: header ? 'semibold' : 'normal', class: alignClass(align), children: children }) })),
29
+ strong: ({ children }) => _jsx("text", { class: "font-bold", children: children }),
30
+ em: ({ children }) => _jsx("text", { class: "italic", children: children }),
31
+ del: ({ children }) => _jsx("text", { class: "line-through opacity-80", children: children }),
32
+ codeSpan: ({ value }) => _jsx("text", { class: "font-mono text-sm bg-base-200 rounded px-1", children: value }),
33
+ link: ({ href, children, onLink }) => (_jsx("text", { class: "text-primary underline", bindtap: () => onLink?.(href), children: children })),
34
+ autolink: ({ href, value, onLink }) => (_jsx("text", { class: "text-primary underline", bindtap: () => onLink?.(href), children: value })),
35
+ image: ({ src, alt, onImageTap }) => (_jsx("text", { class: "text-primary underline", bindtap: () => onImageTap?.(src), children: alt || src })),
36
+ br: () => '\n',
37
+ };
@@ -39,6 +39,23 @@ const daisyColors = {
39
39
  'error': 'var(--color-error)',
40
40
  'error-content': 'var(--color-error-content)',
41
41
  };
42
+ /**
43
+ * Text ramp → token map. Re-points Tailwind's `text-xs`…`text-3xl` font-size
44
+ * utilities at the daisy `--text-*` custom properties (defaults in
45
+ * `styles/themes/tokens.css`, multiplied app-wide by the controller's
46
+ * `fontScale`). Symmetric with `daisyColors`: a single source of truth. Merged
47
+ * via `theme.extend.fontSize`, so the larger Tailwind keys (`text-4xl`+) keep
48
+ * their rem defaults.
49
+ */
50
+ const daisyFontSizes = {
51
+ 'xs': 'var(--text-xs)',
52
+ 'sm': 'var(--text-sm)',
53
+ 'base': 'var(--text-base)',
54
+ 'lg': 'var(--text-lg)',
55
+ 'xl': 'var(--text-xl)',
56
+ '2xl': 'var(--text-2xl)',
57
+ '3xl': 'var(--text-3xl)',
58
+ };
42
59
  const lynxLayoutPlugin = plugin(({ addUtilities }) => {
43
60
  addUtilities({
44
61
  // Long-form flex-fill — the Lynx-correct "take remaining space along
@@ -58,6 +75,7 @@ export const DaisyLynxPreset = {
58
75
  theme: {
59
76
  extend: {
60
77
  colors: daisyColors,
78
+ fontSize: daisyFontSizes,
61
79
  },
62
80
  },
63
81
  plugins: [lynxLayoutPlugin],
@@ -1,5 +1,6 @@
1
1
  /*
2
- * Daisy semantic color utilities.
2
+ * Daisy typography utilities — semantic colors, plus the font-size ramp and
3
+ * font weights (the latter two at the end of this file).
3
4
  *
4
5
  * bg-<token>: every token in DAISY_COLOR_TOKEN_LIST (semantics +
5
6
  * their -content variants, plus the three base surfaces
@@ -64,3 +65,27 @@
64
65
  .bg-warning-content { background-color: var(--color-warning-content); }
65
66
  .bg-error { background-color: var(--color-error); }
66
67
  .bg-error-content { background-color: var(--color-error-content); }
68
+
69
+ /* Font-size ramp — always-on for the same reason as the colors above: the
70
+ * `<Text>` / `<Heading>` components compose `text-<size>` class names
71
+ * dynamically, which a consumer's Tailwind content scanner can't see, so the
72
+ * utilities would otherwise be purged and text falls back to Lynx's native
73
+ * size. These mirror the preset's `text-* → var(--text-*)` mapping (kept in
74
+ * sync), reading the `--text-*` tokens from `themes/tokens.css` (scaled by the
75
+ * controller's `fontScale`). A consumer that DOES scan the package source just
76
+ * regenerates the identical rule — harmless. */
77
+ .text-xs { font-size: var(--text-xs); }
78
+ .text-sm { font-size: var(--text-sm); }
79
+ .text-base { font-size: var(--text-base); }
80
+ .text-lg { font-size: var(--text-lg); }
81
+ .text-xl { font-size: var(--text-xl); }
82
+ .text-2xl { font-size: var(--text-2xl); }
83
+ .text-3xl { font-size: var(--text-3xl); }
84
+
85
+ /* Font weights — always-on for the same reason (composed by `<Text weight>` /
86
+ * `<Heading>`). Values match Tailwind's `font-*` scale. */
87
+ .font-light { font-weight: 300; }
88
+ .font-normal { font-weight: 400; }
89
+ .font-medium { font-weight: 500; }
90
+ .font-semibold { font-weight: 600; }
91
+ .font-bold { font-weight: 700; }
@@ -27,7 +27,28 @@
27
27
  --size-md: 48px;
28
28
  --size-lg: 64px;
29
29
 
30
- /* ── Font sizes ── */
30
+ /* ── Text ramp (public <Text> / <Heading> sizes) ──
31
+ * The xs→3xl scale the `text-*` utilities resolve to (the daisy preset maps
32
+ * Tailwind's fontSize keys onto these vars). Literal px so they resolve on
33
+ * the first paint, like every other structural token. Anchored on a 17px
34
+ * base — the iOS HIG Body size, so bare <Text> (the default) reads as native
35
+ * body — and stepped as an even ~1.2 modular scale (each step ≈1.17–1.21×).
36
+ *
37
+ * The controller's `fontScale` multiplies this ramp app-wide; <ThemeProvider>
38
+ * re-emits the literals in JS (no `calc(var() * n)` — unproven in Lynx).
39
+ * NOTE: keep in sync with FONT_DEFAULTS in theme/ThemeProvider.tsx. */
40
+ --text-xs: 12px;
41
+ --text-sm: 14px;
42
+ --text-base: 17px;
43
+ --text-lg: 20px;
44
+ --text-xl: 24px;
45
+ --text-2xl: 28px;
46
+ --text-3xl: 34px;
47
+
48
+ /* ── Font sizes (control-internal: button / input / badge labels) ──
49
+ * A separate axis from the text ramp above and deliberately NOT scaled with
50
+ * it — control chrome stays fixed. Kept as independent literals (no
51
+ * var→var indirection; unproven in Lynx) even though values mirror the ramp. */
31
52
  --font-xs: 12px;
32
53
  --font-sm: 14px;
33
54
  --font-md: 14px;
@@ -88,6 +88,19 @@ export interface ThemeController {
88
88
  * with no `initial` prop. Useful for a "Reset to system" button.
89
89
  */
90
90
  followSystem(): void;
91
+ /**
92
+ * Current global text-scale multiplier (`1` = the theme's default ramp).
93
+ * Reactive — read inside render/effect to track. Orthogonal to the theme:
94
+ * `set()` / `toggle()` leave it untouched.
95
+ */
96
+ readonly fontScale: number;
97
+ /**
98
+ * Set the global text-scale multiplier — the `--text-*` ramp is re-emitted
99
+ * at `defaultPx × scale`. Persists across theme switches, so it's the place
100
+ * to wire a user accessibility preference or a backend-driven setting (e.g.
101
+ * `setFontScale(1.25)`). Inherits into nested `<ThemeProvider>` subtrees.
102
+ */
103
+ setFontScale(scale: number): void;
91
104
  }
92
105
  /**
93
106
  * Access the active daisyui theme controller. Resolves to the nearest
@@ -118,6 +131,13 @@ Define.Prop<'initial', DaisyTheme, false>
118
131
  * while `followingSystem` is true.
119
132
  */
120
133
  & Define.Prop<'dark', DaisyTheme, false>
134
+ /**
135
+ * Initial global text-scale multiplier (`1` = default ramp). Seeds the
136
+ * controller's `fontScale`; change it later via `controller.setFontScale()`.
137
+ * On the root provider an explicit value wins over any scale a headless
138
+ * caller set before mount.
139
+ */
140
+ & Define.Prop<'fontScale', number, false>
121
141
  /** Extra classes appended to the theme class on the host view. */
122
142
  & Define.Prop<'class', string, false>
123
143
  /** Extra inline style on the host view. Merged after the base flex-fill defaults. */
@@ -39,7 +39,7 @@ import { component, defineInjectable, defineProvide, effect, onMounted, onUnmoun
39
39
  import { useIconColorResolver } from '@sigx/lynx-icons';
40
40
  import { useSystemColorScheme } from '@sigx/lynx-appearance';
41
41
  import { colorsOf, isBuiltInTheme, pickThemeFor, radiusOf, sizesOf, variantOf, } from './registry.js';
42
- import { globalThemeState, makeThemeController, themeController, } from './theme-state.js';
42
+ import { globalThemeState, makeThemeController, normalizeFontScale, themeController, } from './theme-state.js';
43
43
  // DaisyUI v5 expresses control dimensions as multiples of two base units
44
44
  // (`--size-field`, `--size-selector`). Lynx's runtime CSS engine is unproven
45
45
  // for `calc(var() * n)`, so when a theme overrides a base unit we do the
@@ -54,6 +54,12 @@ const SELECTOR_STEPS = {
54
54
  'toggle-thumb-xs': 4, 'toggle-thumb-sm': 4, 'toggle-thumb-md': 5, 'toggle-thumb-lg': 6,
55
55
  'badge-xs': 4, 'badge-sm': 5, 'badge-md': 6, 'badge-lg': 8,
56
56
  };
57
+ // Default text ramp (px) — MUST mirror `--text-*` in `styles/themes/tokens.css`
58
+ // (iOS-aligned, 17px base). The global `fontScale` multiplies these and emits
59
+ // literal px (no `calc(var() * n)` — unproven in Lynx).
60
+ const FONT_DEFAULTS = {
61
+ 'xs': 12, 'sm': 14, 'base': 17, 'lg': 20, 'xl': 24, '2xl': 28, '3xl': 34,
62
+ };
57
63
  const pxValue = (v) => {
58
64
  const m = /^\s*(\d+(?:\.\d+)?)px\s*$/.exec(v);
59
65
  return m ? Number(m[1]) : undefined;
@@ -78,14 +84,28 @@ function applySizeVars(style, sizes) {
78
84
  }
79
85
  }
80
86
  /**
81
- * The full custom-property set for a theme colors plus any radius/size
82
- * overrides. Applied at runtime via the Lynx `setProperty` API (see
87
+ * Emit the text ramp scaled by `fontScale` as `--text-*` literal px. Always
88
+ * emits every step even at `1` (the literal defaults) — because Lynx's
89
+ * `setProperty` only merges and never clears: skipping at `1` would leave a
90
+ * previously-emitted larger ramp stuck after a reset. A nested provider seeds
91
+ * its scale from the inherited ambient value, so emitting here re-states the
92
+ * same ramp rather than clobbering the root's scaled one.
93
+ */
94
+ function applyFontScale(style, fontScale) {
95
+ for (const k in FONT_DEFAULTS) {
96
+ style[`--text-${k}`] = `${Math.round(FONT_DEFAULTS[k] * fontScale)}px`;
97
+ }
98
+ }
99
+ /**
100
+ * The full custom-property set for a theme — colors, any radius/size overrides,
101
+ * and the `fontScale`-adjusted text ramp. Applied at runtime via the Lynx
102
+ * `setProperty` API (see
83
103
  * `<ThemeProvider>`), NOT the inline `style` attribute: Lynx does not honor
84
104
  * custom properties declared inline in this toolchain, but `setProperty`
85
105
  * registers real, inheritable ones — the documented way to theme via CSS
86
106
  * variables (https://lynxjs.org/guide/styling/custom-theming).
87
107
  */
88
- function buildThemeVars(name) {
108
+ function buildThemeVars(name, fontScale) {
89
109
  const palette = colorsOf(name) ?? colorsOf('daisy-light');
90
110
  const radius = radiusOf(name);
91
111
  const sizes = sizesOf(name);
@@ -102,6 +122,7 @@ function buildThemeVars(name) {
102
122
  }
103
123
  if (sizes)
104
124
  applySizeVars(vars, sizes);
125
+ applyFontScale(vars, fontScale);
105
126
  return vars;
106
127
  }
107
128
  /** Unique host id per provider instance so `getElementById` targets its own subtree. */
@@ -123,6 +144,13 @@ export const useTheme = defineInjectable(() => themeController);
123
144
  * global theme or the system bars.
124
145
  */
125
146
  const useThemeDepth = defineInjectable(() => 0);
147
+ /**
148
+ * Ambient text scale inherited by nested providers. A nested `<ThemeProvider>`
149
+ * with no explicit `fontScale` prop seeds from this (the enclosing scale,
150
+ * default 1) instead of resetting to 1 — so the root's scale flows down through
151
+ * color sub-scopes. Each provider re-provides its own current scale.
152
+ */
153
+ const useAmbientFontScale = defineInjectable(() => 1);
126
154
  /**
127
155
  * Wraps children in a `<view class={theme}>` so the daisyui CSS variables
128
156
  * defined inside the theme class inherit down to every descendant.
@@ -151,15 +179,21 @@ export const ThemeProvider = component(({ props, slots }) => {
151
179
  // Stable id for the host view so the runtime `setProperty` call (below) can
152
180
  // target it. Unique per instance so nested providers theme their own subtree.
153
181
  const hostId = `daisy-theme-${++themeIdSeq}`;
182
+ // A nested provider with no explicit `fontScale` inherits the enclosing
183
+ // scale (default 1 at the root), so the root's scale flows down through
184
+ // color sub-scopes rather than resetting. An explicit prop overrides it.
185
+ const ambientFontScale = useAmbientFontScale();
186
+ const seedScale = normalizeFontScale(props.fontScale, ambientFontScale);
154
187
  const state = isRoot
155
188
  ? globalThemeState
156
189
  : signal(props.initial
157
- ? { name: props.initial, following: false }
190
+ ? { name: props.initial, following: false, fontScale: seedScale }
158
191
  : {
159
192
  name: readScheme() === 'dark'
160
193
  ? (props.dark ?? pickThemeFor('dark'))
161
194
  : (props.light ?? pickThemeFor('light')),
162
195
  following: true,
196
+ fontScale: seedScale,
163
197
  });
164
198
  // Seed the root from props/system. An explicit `initial` pin is author
165
199
  // intent and wins. With no `initial`, reflect the current system scheme into
@@ -176,11 +210,18 @@ export const ThemeProvider = component(({ props, slots }) => {
176
210
  ? (props.dark ?? pickThemeFor('dark'))
177
211
  : (props.light ?? pickThemeFor('light'));
178
212
  }
213
+ // Explicit author intent wins; otherwise keep whatever scale a headless
214
+ // caller may have set before this mounted (default 1).
215
+ if (props.fontScale !== undefined) {
216
+ state.fontScale = normalizeFontScale(props.fontScale, state.fontScale);
217
+ }
179
218
  }
180
219
  const controller = isRoot
181
220
  ? themeController
182
221
  : makeThemeController(state);
183
222
  defineProvide(useTheme, () => controller);
223
+ // Re-provide this scope's current scale so nested providers inherit it.
224
+ defineProvide(useAmbientFontScale, () => state.fontScale);
184
225
  // Wire the daisy color resolver into `@sigx/lynx-icons`'s injectable
185
226
  // so any `<Icon variant="primary">` rendered inside this subtree gets
186
227
  // the daisy primary hex automatically. Reading `state.name` inside
@@ -224,9 +265,10 @@ export const ThemeProvider = component(({ props, slots }) => {
224
265
  // `setProperty` path additionally serves runtime-registered themes
225
266
  // (`registerTheme`, no shipped CSS class) — applied once they're
226
267
  // selected post-mount, where it lands reliably. Reading `state.name`
227
- // (via buildThemeVars) tracks it, so this re-runs on every theme change.
268
+ // and `state.fontScale` (via buildThemeVars) tracks them, so this
269
+ // re-runs on every theme change and every `setFontScale`.
228
270
  applyVars = effect(() => {
229
- const vars = buildThemeVars(state.name);
271
+ const vars = buildThemeVars(state.name, state.fontScale);
230
272
  if (typeof lynx !== 'undefined') {
231
273
  lynx.getElementById(hostId)?.setProperty(vars);
232
274
  }
@@ -3,7 +3,21 @@ import type { DaisyTheme, ThemeController } from './ThemeProvider.js';
3
3
  export interface ThemeState {
4
4
  name: DaisyTheme;
5
5
  following: boolean;
6
+ /**
7
+ * Global text-scale multiplier applied on top of the theme's `--text-*`
8
+ * ramp. Orthogonal to `name`: a theme switch / `toggle()` leaves it
9
+ * untouched, so a user/accessibility scale persists across appearance
10
+ * changes. `1` = the default ramp.
11
+ */
12
+ fontScale: number;
6
13
  }
14
+ /**
15
+ * Coerce a font-scale input to a valid positive, finite multiplier. Rejects
16
+ * `NaN`, `±Infinity`, and non-positive values — which would otherwise emit
17
+ * invalid CSS (`NaNpx`, negative font sizes) and break `fontScale === 1`
18
+ * comparisons — by returning `fallback` instead.
19
+ */
20
+ export declare function normalizeFontScale(value: unknown, fallback?: number): number;
7
21
  /**
8
22
  * Build a `ThemeController` over a given state object. Used for both the global
9
23
  * singleton (below) and each nested `<ThemeProvider>`'s local state — same
@@ -20,6 +20,17 @@
20
20
  */
21
21
  import { signal } from '@sigx/lynx';
22
22
  import { pairOf, pickThemeFor } from './registry.js';
23
+ /**
24
+ * Coerce a font-scale input to a valid positive, finite multiplier. Rejects
25
+ * `NaN`, `±Infinity`, and non-positive values — which would otherwise emit
26
+ * invalid CSS (`NaNpx`, negative font sizes) and break `fontScale === 1`
27
+ * comparisons — by returning `fallback` instead.
28
+ */
29
+ export function normalizeFontScale(value, fallback = 1) {
30
+ return typeof value === 'number' && Number.isFinite(value) && value > 0
31
+ ? value
32
+ : fallback;
33
+ }
23
34
  /**
24
35
  * Build a `ThemeController` over a given state object. Used for both the global
25
36
  * singleton (below) and each nested `<ThemeProvider>`'s local state — same
@@ -34,6 +45,9 @@ export function makeThemeController(state) {
34
45
  get followingSystem() {
35
46
  return state.following;
36
47
  },
48
+ get fontScale() {
49
+ return state.fontScale;
50
+ },
37
51
  set(next) {
38
52
  state.name = next;
39
53
  state.following = false;
@@ -45,6 +59,10 @@ export function makeThemeController(state) {
45
59
  followSystem() {
46
60
  state.following = true;
47
61
  },
62
+ setFontScale(scale) {
63
+ // Ignore invalid input (keep the current scale) so state stays valid.
64
+ state.fontScale = normalizeFontScale(scale, state.fontScale);
65
+ },
48
66
  };
49
67
  }
50
68
  // Object signal (not primitive) so the `DaisyTheme` literal union survives —
@@ -54,6 +72,7 @@ export function makeThemeController(state) {
54
72
  const state = signal({
55
73
  name: pickThemeFor('light'),
56
74
  following: true,
75
+ fontScale: 1,
57
76
  });
58
77
  /**
59
78
  * The backing signal for the global theme. Read/written by the root
@@ -8,11 +8,21 @@ const weightClasses = {
8
8
  light: 'font-light', normal: 'font-normal', medium: 'font-medium',
9
9
  semibold: 'font-semibold', bold: 'font-bold',
10
10
  };
11
+ // A `text-<size>` font-size utility already present in `class` (the common
12
+ // `class="text-sm"` override idiom). The trailing `(?![\w-])` guard excludes
13
+ // color tokens like `text-base-content`, so they don't suppress the default.
14
+ const SIZE_IN_CLASS = /(?:^|\s)text-(?:xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)(?![\w-])/;
11
15
  export const Text = component(({ props, slots }) => {
12
16
  const getClasses = () => {
13
17
  const c = [];
18
+ // Defined default: `base` (--text-base, 17px) so text has a token-driven
19
+ // size instead of Lynx's native <text> default — unless the caller set an
20
+ // explicit `size` prop or already passed a `text-*` size through `class`
21
+ // (avoids emitting two conflicting font-size utilities).
14
22
  if (props.size)
15
23
  c.push(sizeClasses[props.size]);
24
+ else if (!(props.class && SIZE_IN_CLASS.test(props.class)))
25
+ c.push(sizeClasses.base);
16
26
  if (props.weight)
17
27
  c.push(weightClasses[props.weight]);
18
28
  if (props.color)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/lynx-daisyui",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "DaisyUI integration for sigx-lynx",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,17 +37,21 @@
37
37
  "LICENSE"
38
38
  ],
39
39
  "dependencies": {
40
- "@sigx/lynx": "^0.4.4",
41
- "@sigx/lynx-appearance": "^0.4.4",
42
- "@sigx/lynx-gestures": "^0.4.4",
43
- "@sigx/lynx-icons": "^0.4.4",
44
- "@sigx/lynx-motion": "^0.4.4"
40
+ "@sigx/lynx-appearance": "^0.4.6",
41
+ "@sigx/lynx": "^0.4.6",
42
+ "@sigx/lynx-icons": "^0.4.6",
43
+ "@sigx/lynx-gestures": "^0.4.6",
44
+ "@sigx/lynx-motion": "^0.4.6"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "tailwindcss": "^3.0.0 || ^4.0.0",
48
- "@sigx/lynx-navigation": "^0.4.4"
48
+ "@sigx/lynx-markdown": "^0.4.6",
49
+ "@sigx/lynx-navigation": "^0.4.6"
49
50
  },
50
51
  "peerDependenciesMeta": {
52
+ "@sigx/lynx-markdown": {
53
+ "optional": true
54
+ },
51
55
  "@sigx/lynx-navigation": {
52
56
  "optional": true
53
57
  }
@@ -56,7 +60,8 @@
56
60
  "@typescript/native-preview": "7.0.0-dev.20260521.1",
57
61
  "tailwindcss": "^4.0.0",
58
62
  "typescript": "^6.0.3",
59
- "@sigx/lynx-navigation": "^0.4.4"
63
+ "@sigx/lynx-markdown": "^0.4.6",
64
+ "@sigx/lynx-navigation": "^0.4.6"
60
65
  },
61
66
  "publishConfig": {
62
67
  "access": "public"