@idealyst/theme 1.2.71 → 1.2.73

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/builder.ts +292 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/theme",
3
- "version": "1.2.71",
3
+ "version": "1.2.73",
4
4
  "description": "Theming system for Idealyst Framework",
5
5
  "readme": "README.md",
6
6
  "main": "src/index.ts",
package/src/builder.ts CHANGED
@@ -32,6 +32,42 @@ import {
32
32
  ViewSizeValue,
33
33
  } from './theme/structures';
34
34
 
35
+ /**
36
+ * Mapping of component names to their size value types.
37
+ * Used for type-safe addSize/setSize methods.
38
+ */
39
+ export type ComponentSizeMap = {
40
+ button: ButtonSizeValue;
41
+ iconButton: IconButtonSizeValue;
42
+ chip: ChipSizeValue;
43
+ badge: BadgeSizeValue;
44
+ icon: IconSizeValue;
45
+ input: InputSizeValue;
46
+ radioButton: RadioButtonSizeValue;
47
+ select: SelectSizeValue;
48
+ slider: SliderSizeValue;
49
+ switch: SwitchSizeValue;
50
+ textarea: TextAreaSizeValue;
51
+ avatar: AvatarSizeValue;
52
+ progress: ProgressSizeValue;
53
+ accordion: AccordionSizeValue;
54
+ activityIndicator: ActivityIndicatorSizeValue;
55
+ alert: AlertSizeValue;
56
+ breadcrumb: BreadcrumbSizeValue;
57
+ list: ListSizeValue;
58
+ menu: MenuSizeValue;
59
+ text: TextSizeValue;
60
+ tabBar: TabBarSizeValue;
61
+ table: TableSizeValue;
62
+ tooltip: TooltipSizeValue;
63
+ view: ViewSizeValue;
64
+ };
65
+
66
+ /**
67
+ * Valid component names for size methods.
68
+ */
69
+ export type SizeableComponent = keyof ComponentSizeMap;
70
+
35
71
  /**
36
72
  * Built theme structure - self-contained, no external type dependencies.
37
73
  */
@@ -113,6 +149,7 @@ type ThemeConfig<
113
149
  * .addIntent('brand', { primary: '#6366f1', contrast: '#fff', light: '#818cf8', dark: '#4f46e5' })
114
150
  * .addRadius('sm', 4)
115
151
  * .addRadius('full', 9999)
152
+ * .addSize('button', '2xl', { paddingVertical: 14, paddingHorizontal: 28, ... })
116
153
  * .build();
117
154
  *
118
155
  * // Register the theme type
@@ -155,6 +192,10 @@ export class ThemeBuilder<
155
192
  };
156
193
  }
157
194
 
195
+ // =========================================================================
196
+ // Intent Methods
197
+ // =========================================================================
198
+
158
199
  /**
159
200
  * Add a custom intent to the theme.
160
201
  */
@@ -192,6 +233,10 @@ export class ThemeBuilder<
192
233
  return newBuilder;
193
234
  }
194
235
 
236
+ // =========================================================================
237
+ // Radius Methods
238
+ // =========================================================================
239
+
195
240
  /**
196
241
  * Add a custom border radius value.
197
242
  */
@@ -210,6 +255,29 @@ export class ThemeBuilder<
210
255
  return newBuilder;
211
256
  }
212
257
 
258
+ /**
259
+ * Set (replace) an existing radius value in the theme.
260
+ * Use this to override a radius inherited from a base theme.
261
+ */
262
+ setRadius<K extends TRadii>(
263
+ name: K,
264
+ value: number
265
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
266
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
267
+ newBuilder.config = {
268
+ ...this.config,
269
+ radii: {
270
+ ...this.config.radii,
271
+ [name]: value,
272
+ } as any,
273
+ };
274
+ return newBuilder;
275
+ }
276
+
277
+ // =========================================================================
278
+ // Shadow Methods
279
+ // =========================================================================
280
+
213
281
  /**
214
282
  * Add a custom shadow value.
215
283
  */
@@ -228,6 +296,29 @@ export class ThemeBuilder<
228
296
  return newBuilder;
229
297
  }
230
298
 
299
+ /**
300
+ * Set (replace) an existing shadow value in the theme.
301
+ * Use this to override a shadow inherited from a base theme.
302
+ */
303
+ setShadow<K extends TShadows>(
304
+ name: K,
305
+ value: ShadowValue
306
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
307
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
308
+ newBuilder.config = {
309
+ ...this.config,
310
+ shadows: {
311
+ ...this.config.shadows,
312
+ [name]: value,
313
+ } as any,
314
+ };
315
+ return newBuilder;
316
+ }
317
+
318
+ // =========================================================================
319
+ // Interaction Methods
320
+ // =========================================================================
321
+
231
322
  /**
232
323
  * Set the interaction configuration.
233
324
  */
@@ -242,6 +333,46 @@ export class ThemeBuilder<
242
333
  return newBuilder;
243
334
  }
244
335
 
336
+ /**
337
+ * Update specific interaction properties without replacing the entire config.
338
+ * Use this to modify individual opacity values or focus styles.
339
+ *
340
+ * @example
341
+ * ```typescript
342
+ * fromTheme(lightTheme)
343
+ * .updateInteraction({ opacity: { disabled: 0.3 } })
344
+ * .build();
345
+ * ```
346
+ */
347
+ updateInteraction(
348
+ partial: {
349
+ focusedBackground?: string;
350
+ focusBorder?: string;
351
+ opacity?: Partial<InteractionConfig['opacity']>;
352
+ }
353
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
354
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
355
+ const currentInteraction = this.config.interaction ?? {} as InteractionConfig;
356
+ const currentOpacity = currentInteraction.opacity ?? { hover: 0.9, active: 0.75, disabled: 0.5 };
357
+
358
+ newBuilder.config = {
359
+ ...this.config,
360
+ interaction: {
361
+ focusedBackground: partial.focusedBackground ?? currentInteraction.focusedBackground,
362
+ focusBorder: partial.focusBorder ?? currentInteraction.focusBorder,
363
+ opacity: {
364
+ ...currentOpacity,
365
+ ...partial.opacity,
366
+ },
367
+ },
368
+ };
369
+ return newBuilder;
370
+ }
371
+
372
+ // =========================================================================
373
+ // Color Methods
374
+ // =========================================================================
375
+
245
376
  /**
246
377
  * Set the colors configuration.
247
378
  */
@@ -440,8 +571,12 @@ export class ThemeBuilder<
440
571
  return newBuilder;
441
572
  }
442
573
 
574
+ // =========================================================================
575
+ // Size Methods
576
+ // =========================================================================
577
+
443
578
  /**
444
- * Set the sizes configuration.
579
+ * Set all sizes at once.
445
580
  */
446
581
  setSizes<S extends string>(sizes: {
447
582
  button: Record<S, ButtonSizeValue>;
@@ -478,6 +613,132 @@ export class ThemeBuilder<
478
613
  return newBuilder;
479
614
  }
480
615
 
616
+ /**
617
+ * Add a new size variant for a specific component.
618
+ * This adds the size to all components in the theme.
619
+ *
620
+ * @param component - The component type (e.g., 'button', 'input', 'avatar')
621
+ * @param name - The size name (e.g., '2xl', 'compact', 'tiny')
622
+ * @param value - The size values for that component
623
+ *
624
+ * @example
625
+ * ```typescript
626
+ * createTheme()
627
+ * .addSize('button', '2xl', {
628
+ * paddingVertical: 14,
629
+ * paddingHorizontal: 28,
630
+ * minHeight: 64,
631
+ * fontSize: 22,
632
+ * lineHeight: 36,
633
+ * iconSize: 22,
634
+ * })
635
+ * .addSize('input', '2xl', {
636
+ * height: 64,
637
+ * paddingHorizontal: 20,
638
+ * fontSize: 18,
639
+ * iconSize: 24,
640
+ * iconMargin: 12,
641
+ * })
642
+ * .build();
643
+ * ```
644
+ */
645
+ addSize<C extends SizeableComponent, K extends string>(
646
+ component: C,
647
+ name: K,
648
+ value: ComponentSizeMap[C]
649
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize | K, TBreakpoints> {
650
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize | K, TBreakpoints>();
651
+ newBuilder.config = {
652
+ ...this.config,
653
+ sizes: {
654
+ ...this.config.sizes,
655
+ [component]: {
656
+ ...((this.config.sizes as any)?.[component] ?? {}),
657
+ [name]: value,
658
+ },
659
+ } as any,
660
+ };
661
+ return newBuilder;
662
+ }
663
+
664
+ /**
665
+ * Set (replace) an existing size variant for a specific component.
666
+ * Use this to override a size inherited from a base theme.
667
+ *
668
+ * @param component - The component type (e.g., 'button', 'input', 'avatar')
669
+ * @param name - The existing size name to override
670
+ * @param value - The new size values for that component
671
+ *
672
+ * @example
673
+ * ```typescript
674
+ * fromTheme(lightTheme)
675
+ * .setSize('button', 'md', {
676
+ * paddingVertical: 10,
677
+ * paddingHorizontal: 20,
678
+ * minHeight: 44,
679
+ * fontSize: 18,
680
+ * lineHeight: 28,
681
+ * iconSize: 18,
682
+ * })
683
+ * .build();
684
+ * ```
685
+ */
686
+ setSize<C extends SizeableComponent, K extends TSize>(
687
+ component: C,
688
+ name: K,
689
+ value: ComponentSizeMap[C]
690
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
691
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
692
+ newBuilder.config = {
693
+ ...this.config,
694
+ sizes: {
695
+ ...this.config.sizes,
696
+ [component]: {
697
+ ...((this.config.sizes as any)?.[component] ?? {}),
698
+ [name]: value,
699
+ },
700
+ } as any,
701
+ };
702
+ return newBuilder;
703
+ }
704
+
705
+ // =========================================================================
706
+ // Typography Methods
707
+ // =========================================================================
708
+
709
+ /**
710
+ * Set (replace) a typography variant in the theme.
711
+ * Typography variants use a fixed set of names (h1-h6, subtitle1-2, body1-2, caption).
712
+ *
713
+ * @example
714
+ * ```typescript
715
+ * fromTheme(lightTheme)
716
+ * .setTypography('h1', { fontSize: 40, lineHeight: 48, fontWeight: '700' })
717
+ * .build();
718
+ * ```
719
+ */
720
+ setTypography<K extends Typography>(
721
+ name: K,
722
+ value: TypographyValue
723
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
724
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
725
+ newBuilder.config = {
726
+ ...this.config,
727
+ sizes: {
728
+ ...this.config.sizes,
729
+ typography: {
730
+ ...(this.config.sizes?.typography ?? {}),
731
+ [name]: value,
732
+ },
733
+ } as any,
734
+ };
735
+ return newBuilder;
736
+ }
737
+
738
+ // =========================================================================
739
+ // Breakpoint Methods
740
+ // =========================================================================
741
+
481
742
  /**
482
743
  * Add a single breakpoint to the theme.
483
744
  *
@@ -511,6 +772,32 @@ export class ThemeBuilder<
511
772
  return newBuilder;
512
773
  }
513
774
 
775
+ /**
776
+ * Set (replace) an existing breakpoint value.
777
+ * Use this to override a breakpoint inherited from a base theme.
778
+ *
779
+ * @example
780
+ * ```typescript
781
+ * fromTheme(lightTheme)
782
+ * .setBreakpoint('md', 800) // Change md breakpoint from 768 to 800
783
+ * .build();
784
+ * ```
785
+ */
786
+ setBreakpoint<K extends TBreakpoints>(
787
+ name: K,
788
+ value: number
789
+ ): ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints> {
790
+ const newBuilder = new ThemeBuilder<TIntents, TRadii, TShadows, TPallet, TSurface, TText, TBorder, TSize, TBreakpoints>();
791
+ newBuilder.config = {
792
+ ...this.config,
793
+ breakpoints: {
794
+ ...this.config.breakpoints,
795
+ [name]: value,
796
+ } as any,
797
+ };
798
+ return newBuilder;
799
+ }
800
+
514
801
  /**
515
802
  * Set all breakpoints at once.
516
803
  *
@@ -543,6 +830,10 @@ export class ThemeBuilder<
543
830
  return newBuilder;
544
831
  }
545
832
 
833
+ // =========================================================================
834
+ // Build
835
+ // =========================================================================
836
+
546
837
  /**
547
838
  * Build the final theme object.
548
839
  */