@fakhrirafiki/theme-engine 0.4.2 → 0.4.3

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.js CHANGED
@@ -4636,6 +4636,7 @@ var PresetButton = ({
4636
4636
  renderColorBox
4637
4637
  }) => {
4638
4638
  const colors = preset.colors[mode];
4639
+ const label = preset.name.replace(/-/g, " ");
4639
4640
  if (renderPreset) {
4640
4641
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4641
4642
  "div",
@@ -4647,23 +4648,23 @@ var PresetButton = ({
4647
4648
  }
4648
4649
  );
4649
4650
  }
4650
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex-shrink-0", style: { minWidth: layout.buttonWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4651
- "div",
4651
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex-shrink-0", style: { minWidth: layout.buttonWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
4652
+ "button",
4652
4653
  {
4654
+ type: "button",
4653
4655
  className: (0, import_clsx2.clsx)(
4654
4656
  "theme-preset-button",
4655
- "cursor-pointer bg-card hover:bg-card/80 border border-border rounded-lg",
4656
- "flex w-full h-full items-center justify-center relative transition-all duration-200",
4657
- "hover:shadow-lg hover:border-primary/20 px-4 py-3",
4658
- isSelected ? "ring-2 ring-primary/50 shadow-md bg-primary/5" : ""
4657
+ isSelected && "theme-preset-button--selected"
4659
4658
  ),
4660
4659
  onClick,
4661
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2.5 text-center", children: [
4662
- layout.showColorBoxes && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex gap-1", children: [colors.primary, colors.secondary, colors.accent].slice(0, layout.colorBoxCount).map(
4660
+ "aria-pressed": isSelected,
4661
+ title: label,
4662
+ children: [
4663
+ layout.showColorBoxes && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "theme-preset-button__colors", children: [colors.primary, colors.secondary, colors.accent].slice(0, layout.colorBoxCount).map(
4663
4664
  (color, index) => renderColorBox ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: renderColorBox(color, index) }, index) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ColorBox, { color }, index)
4664
4665
  ) }),
4665
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "capitalize px-1 leading-tight text-sm font-medium text-foreground", children: preset.name.replace(/-/g, " ") })
4666
- ] })
4666
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "theme-preset-button__text", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "theme-preset-button__label", children: label }) })
4667
+ ]
4667
4668
  }
4668
4669
  ) });
4669
4670
  };
@@ -4747,41 +4748,45 @@ var ThemePresetButtons = ({
4747
4748
  try {
4748
4749
  setLoading(true);
4749
4750
  setError(null);
4750
- let allPresets = [];
4751
+ const builtInPresetList = [];
4752
+ const customPresetList = [];
4751
4753
  if (showBuiltIn) {
4752
- const builtInPresetList = Object.entries(builtInPresets).map(([id, preset]) => ({
4753
- id,
4754
- name: preset.label,
4755
- colors: {
4756
- light: preset.styles.light,
4757
- dark: preset.styles.dark
4758
- },
4759
- metadata: {
4760
- category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4761
- tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4762
- createdAt: preset.createdAt,
4763
- provider: "built-in"
4764
- }
4765
- }));
4766
- allPresets.push(...builtInPresetList);
4754
+ builtInPresetList.push(
4755
+ ...Object.entries(builtInPresets).map(([id, preset]) => ({
4756
+ id,
4757
+ name: preset.label,
4758
+ colors: {
4759
+ light: preset.styles.light,
4760
+ dark: preset.styles.dark
4761
+ },
4762
+ metadata: {
4763
+ category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4764
+ tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4765
+ createdAt: preset.createdAt,
4766
+ provider: "built-in"
4767
+ }
4768
+ }))
4769
+ );
4767
4770
  }
4768
4771
  if (showCustom) {
4769
- const customPresetList = Object.entries(customPresets).map(([id, preset]) => ({
4770
- id,
4771
- name: preset.label,
4772
- colors: {
4773
- light: preset.styles.light,
4774
- dark: preset.styles.dark
4775
- },
4776
- metadata: {
4777
- category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4778
- tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4779
- createdAt: preset.createdAt,
4780
- provider: "custom"
4781
- }
4782
- }));
4783
- allPresets.push(...customPresetList);
4772
+ customPresetList.push(
4773
+ ...Object.entries(customPresets).map(([id, preset]) => ({
4774
+ id,
4775
+ name: preset.label,
4776
+ colors: {
4777
+ light: preset.styles.light,
4778
+ dark: preset.styles.dark
4779
+ },
4780
+ metadata: {
4781
+ category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4782
+ tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4783
+ createdAt: preset.createdAt,
4784
+ provider: "custom"
4785
+ }
4786
+ }))
4787
+ );
4784
4788
  }
4789
+ let allPresets = [...customPresetList, ...builtInPresetList];
4785
4790
  if (categories && categories.length > 0) {
4786
4791
  allPresets = allPresets.filter(
4787
4792
  (preset) => categories.includes(preset.metadata?.category || "unknown")
package/dist/index.mjs CHANGED
@@ -4593,6 +4593,7 @@ var PresetButton = ({
4593
4593
  renderColorBox
4594
4594
  }) => {
4595
4595
  const colors = preset.colors[mode];
4596
+ const label = preset.name.replace(/-/g, " ");
4596
4597
  if (renderPreset) {
4597
4598
  return /* @__PURE__ */ jsx4(
4598
4599
  "div",
@@ -4604,23 +4605,23 @@ var PresetButton = ({
4604
4605
  }
4605
4606
  );
4606
4607
  }
4607
- return /* @__PURE__ */ jsx4("div", { className: "flex-shrink-0", style: { minWidth: layout.buttonWidth }, children: /* @__PURE__ */ jsx4(
4608
- "div",
4608
+ return /* @__PURE__ */ jsx4("div", { className: "flex-shrink-0", style: { minWidth: layout.buttonWidth }, children: /* @__PURE__ */ jsxs3(
4609
+ "button",
4609
4610
  {
4611
+ type: "button",
4610
4612
  className: clsx2(
4611
4613
  "theme-preset-button",
4612
- "cursor-pointer bg-card hover:bg-card/80 border border-border rounded-lg",
4613
- "flex w-full h-full items-center justify-center relative transition-all duration-200",
4614
- "hover:shadow-lg hover:border-primary/20 px-4 py-3",
4615
- isSelected ? "ring-2 ring-primary/50 shadow-md bg-primary/5" : ""
4614
+ isSelected && "theme-preset-button--selected"
4616
4615
  ),
4617
4616
  onClick,
4618
- children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2.5 text-center", children: [
4619
- layout.showColorBoxes && /* @__PURE__ */ jsx4("div", { className: "flex gap-1", children: [colors.primary, colors.secondary, colors.accent].slice(0, layout.colorBoxCount).map(
4617
+ "aria-pressed": isSelected,
4618
+ title: label,
4619
+ children: [
4620
+ layout.showColorBoxes && /* @__PURE__ */ jsx4("div", { className: "theme-preset-button__colors", children: [colors.primary, colors.secondary, colors.accent].slice(0, layout.colorBoxCount).map(
4620
4621
  (color, index) => renderColorBox ? /* @__PURE__ */ jsx4("span", { children: renderColorBox(color, index) }, index) : /* @__PURE__ */ jsx4(ColorBox, { color }, index)
4621
4622
  ) }),
4622
- /* @__PURE__ */ jsx4("span", { className: "capitalize px-1 leading-tight text-sm font-medium text-foreground", children: preset.name.replace(/-/g, " ") })
4623
- ] })
4623
+ /* @__PURE__ */ jsx4("div", { className: "theme-preset-button__text", children: /* @__PURE__ */ jsx4("span", { className: "theme-preset-button__label", children: label }) })
4624
+ ]
4624
4625
  }
4625
4626
  ) });
4626
4627
  };
@@ -4704,41 +4705,45 @@ var ThemePresetButtons = ({
4704
4705
  try {
4705
4706
  setLoading(true);
4706
4707
  setError(null);
4707
- let allPresets = [];
4708
+ const builtInPresetList = [];
4709
+ const customPresetList = [];
4708
4710
  if (showBuiltIn) {
4709
- const builtInPresetList = Object.entries(builtInPresets).map(([id, preset]) => ({
4710
- id,
4711
- name: preset.label,
4712
- colors: {
4713
- light: preset.styles.light,
4714
- dark: preset.styles.dark
4715
- },
4716
- metadata: {
4717
- category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4718
- tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4719
- createdAt: preset.createdAt,
4720
- provider: "built-in"
4721
- }
4722
- }));
4723
- allPresets.push(...builtInPresetList);
4711
+ builtInPresetList.push(
4712
+ ...Object.entries(builtInPresets).map(([id, preset]) => ({
4713
+ id,
4714
+ name: preset.label,
4715
+ colors: {
4716
+ light: preset.styles.light,
4717
+ dark: preset.styles.dark
4718
+ },
4719
+ metadata: {
4720
+ category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4721
+ tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4722
+ createdAt: preset.createdAt,
4723
+ provider: "built-in"
4724
+ }
4725
+ }))
4726
+ );
4724
4727
  }
4725
4728
  if (showCustom) {
4726
- const customPresetList = Object.entries(customPresets).map(([id, preset]) => ({
4727
- id,
4728
- name: preset.label,
4729
- colors: {
4730
- light: preset.styles.light,
4731
- dark: preset.styles.dark
4732
- },
4733
- metadata: {
4734
- category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4735
- tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4736
- createdAt: preset.createdAt,
4737
- provider: "custom"
4738
- }
4739
- }));
4740
- allPresets.push(...customPresetList);
4729
+ customPresetList.push(
4730
+ ...Object.entries(customPresets).map(([id, preset]) => ({
4731
+ id,
4732
+ name: preset.label,
4733
+ colors: {
4734
+ light: preset.styles.light,
4735
+ dark: preset.styles.dark
4736
+ },
4737
+ metadata: {
4738
+ category: preset.label.toLowerCase().includes("minimal") ? "minimal" : preset.label.toLowerCase().includes("violet") || preset.label.toLowerCase().includes("purple") ? "vibrant" : "modern",
4739
+ tags: [preset.label.toLowerCase().replace(/\s+/g, "-")],
4740
+ createdAt: preset.createdAt,
4741
+ provider: "custom"
4742
+ }
4743
+ }))
4744
+ );
4741
4745
  }
4746
+ let allPresets = [...customPresetList, ...builtInPresetList];
4742
4747
  if (categories && categories.length > 0) {
4743
4748
  allPresets = allPresets.filter(
4744
4749
  (preset) => categories.includes(preset.metadata?.category || "unknown")
@@ -40,14 +40,80 @@
40
40
 
41
41
  /* ThemePresetButtons: lightweight CSS-based animations and hover affordances */
42
42
 
43
- /* ThemePresetButtons: hover affordance without motion library */
43
+ /* ThemePresetButtons: base button styling (no Tailwind required) */
44
44
  .theme-preset-button {
45
- transition: transform 0.2s ease-out;
45
+ width: 100%;
46
+ height: 56px;
47
+ padding: 0.75rem 0.875rem;
48
+
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: flex-start;
52
+ gap: 0.625rem;
53
+
54
+ border-radius: calc(var(--radius) + 0.25rem);
55
+ border: 1px solid hsl(var(--border) / 0.75);
56
+ background: hsl(var(--card) / 0.85);
57
+ color: hsl(var(--foreground));
58
+
59
+ box-shadow: 0 1px 0 hsl(var(--border) / 0.35);
60
+ cursor: pointer;
61
+
62
+ transition:
63
+ transform 0.2s ease-out,
64
+ background-color 0.2s ease-out,
65
+ border-color 0.2s ease-out,
66
+ box-shadow 0.2s ease-out;
67
+ }
68
+
69
+ .theme-preset-button:focus-visible {
70
+ outline: 2px solid hsl(var(--ring) / 0.75);
71
+ outline-offset: 2px;
72
+ }
73
+
74
+ .theme-preset-button:disabled {
75
+ opacity: 0.6;
76
+ cursor: not-allowed;
77
+ }
78
+
79
+ .theme-preset-button--selected {
80
+ background: hsl(var(--primary) / 0.06);
81
+ border-color: hsl(var(--primary) / 0.35);
82
+ box-shadow: 0 0 0 2px hsl(var(--primary) / 0.25);
83
+ }
84
+
85
+ .theme-preset-button__colors {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 0.25rem;
89
+ flex-shrink: 0;
90
+ }
91
+
92
+ .theme-preset-button__text {
93
+ min-width: 0;
94
+ flex: 1;
95
+ }
96
+
97
+ .theme-preset-button__label {
98
+ display: -webkit-box;
99
+ -webkit-box-orient: vertical;
100
+ -webkit-line-clamp: 2;
101
+ overflow: hidden;
102
+
103
+ line-height: 1.1;
104
+ font-size: 0.875rem;
105
+ font-weight: 500;
106
+ text-transform: capitalize;
46
107
  }
47
108
 
48
109
  .theme-preset-button:hover {
49
- transform: translateY(-3px) scale(1.02);
110
+ transform: translateY(-2px) scale(1.01);
50
111
  z-index: 20;
112
+ background: hsl(var(--card) / 0.95);
113
+ border-color: hsl(var(--primary) / 0.2);
114
+ box-shadow:
115
+ 0 10px 25px hsl(0 0% 0% / 0.12),
116
+ 0 0 0 1px hsl(var(--border) / 0.35);
51
117
  }
52
118
 
53
119
  /* Color boxes within preset buttons - fallback only */
@@ -55,11 +121,12 @@
55
121
  width: 12px;
56
122
  height: 12px;
57
123
  border-radius: calc(var(--radius) - 4px);
58
- border: 1px solid rgba(0, 0, 0, 0.1);
124
+ border: 1px solid hsl(var(--border) / 0.75);
125
+ box-shadow: 0 1px 0 hsl(var(--border) / 0.3);
59
126
  }
60
127
 
61
128
  .dark .theme-color-box {
62
- border-color: rgba(255, 255, 255, 0.1);
129
+ border-color: hsl(var(--border) / 0.4);
63
130
  }
64
131
 
65
132
  /* Theme status card - for debugging and demos */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fakhrirafiki/theme-engine",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Elegant theming system with smooth transitions, custom presets, semantic accent colors, and complete shadcn/ui support for modern React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",