funuicss 3.6.6 → 3.6.7

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.6.6",
2
+ "version": "3.6.7",
3
3
  "name": "funuicss",
4
4
  "description": "React and Next.js component UI Library for creating Easy and good looking websites with fewer lines of code. Elevate your web development experience with our cutting-edge React/Next.js component UI Library. Craft stunning websites effortlessly, boasting both seamless functionality and aesthetic appeal—all achieved with minimal lines of code. Unleash the power of simplicity and style in your projects!",
5
5
  "main": "index.js",
@@ -1,5 +1,4 @@
1
- import { ReactNode } from 'react';
2
- import * as React from 'react';
1
+ import React, { ReactNode, MouseEvent } from 'react';
3
2
  interface ButtonProps {
4
3
  color?: string;
5
4
  bg?: string;
@@ -30,10 +29,11 @@ interface ButtonProps {
30
29
  buttonFillStyle?: React.CSSProperties;
31
30
  outlineSize?: number;
32
31
  isLoading?: boolean;
32
+ variant?: string;
33
33
  status?: 'success' | 'warning' | 'info' | 'danger';
34
34
  children?: React.ReactNode;
35
35
  style?: React.CSSProperties;
36
- onClick?: (...args: unknown[]) => void;
36
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
37
37
  }
38
- export default function Button({ color, bg, funcss, startIcon, endIcon, text, rounded, raised, height, width, float, hoverUp, fullWidth, outlined, small, hoverless, smaller, big, bigger, jumbo, flat, hoverNone, fillAnimation, fillDirection, fillTextColor, outlineSize, isLoading, status, children, bold, style, onClick, ...rest }: ButtonProps): React.JSX.Element;
38
+ export default function Button({ variant, color, bg, funcss, startIcon, endIcon, text, rounded, raised, height, width, float, hoverUp, fullWidth, outlined, small, hoverless, smaller, big, bigger, jumbo, flat, hoverNone, fillAnimation, fillDirection, fillTextColor, outlineSize, isLoading, status, children, bold, style, onClick, ...rest }: ButtonProps): React.JSX.Element;
39
39
  export {};
@@ -11,39 +11,6 @@ var __assign = (this && this.__assign) || function () {
11
11
  };
12
12
  return __assign.apply(this, arguments);
13
13
  };
14
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- var desc = Object.getOwnPropertyDescriptor(m, k);
17
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
- desc = { enumerable: true, get: function() { return m[k]; } };
19
- }
20
- Object.defineProperty(o, k2, desc);
21
- }) : (function(o, m, k, k2) {
22
- if (k2 === undefined) k2 = k;
23
- o[k2] = m[k];
24
- }));
25
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
- Object.defineProperty(o, "default", { enumerable: true, value: v });
27
- }) : function(o, v) {
28
- o["default"] = v;
29
- });
30
- var __importStar = (this && this.__importStar) || (function () {
31
- var ownKeys = function(o) {
32
- ownKeys = Object.getOwnPropertyNames || function (o) {
33
- var ar = [];
34
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
- return ar;
36
- };
37
- return ownKeys(o);
38
- };
39
- return function (mod) {
40
- if (mod && mod.__esModule) return mod;
41
- var result = {};
42
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
- __setModuleDefault(result, mod);
44
- return result;
45
- };
46
- })();
47
14
  var __rest = (this && this.__rest) || function (s, e) {
48
15
  var t = {};
49
16
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -55,57 +22,103 @@ var __rest = (this && this.__rest) || function (s, e) {
55
22
  }
56
23
  return t;
57
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
58
28
  Object.defineProperty(exports, "__esModule", { value: true });
59
29
  exports.default = Button;
60
- var React = __importStar(require("react"));
30
+ var react_1 = __importDefault(require("react"));
61
31
  var pi_1 = require("react-icons/pi");
32
+ var componentUtils_1 = require("../../utils/componentUtils");
62
33
  function Button(_a) {
63
- var color = _a.color, bg = _a.bg, funcss = _a.funcss, startIcon = _a.startIcon, endIcon = _a.endIcon, text = _a.text, rounded = _a.rounded, raised = _a.raised, height = _a.height, width = _a.width, float = _a.float, hoverUp = _a.hoverUp, fullWidth = _a.fullWidth, outlined = _a.outlined, small = _a.small, hoverless = _a.hoverless, smaller = _a.smaller, big = _a.big, bigger = _a.bigger, jumbo = _a.jumbo, flat = _a.flat, hoverNone = _a.hoverNone, fillAnimation = _a.fillAnimation, fillDirection = _a.fillDirection, fillTextColor = _a.fillTextColor, outlineSize = _a.outlineSize, isLoading = _a.isLoading, status = _a.status, children = _a.children, bold = _a.bold, style = _a.style, onClick = _a.onClick, rest = __rest(_a, ["color", "bg", "funcss", "startIcon", "endIcon", "text", "rounded", "raised", "height", "width", "float", "hoverUp", "fullWidth", "outlined", "small", "hoverless", "smaller", "big", "bigger", "jumbo", "flat", "hoverNone", "fillAnimation", "fillDirection", "fillTextColor", "outlineSize", "isLoading", "status", "children", "bold", "style", "onClick"]);
34
+ var _b = _a.variant, variant = _b === void 0 ? '' : _b, color = _a.color, bg = _a.bg, funcss = _a.funcss, startIcon = _a.startIcon, endIcon = _a.endIcon, text = _a.text, rounded = _a.rounded, raised = _a.raised, height = _a.height, width = _a.width, float = _a.float, hoverUp = _a.hoverUp, fullWidth = _a.fullWidth, outlined = _a.outlined, small = _a.small, hoverless = _a.hoverless, smaller = _a.smaller, big = _a.big, bigger = _a.bigger, jumbo = _a.jumbo, flat = _a.flat, hoverNone = _a.hoverNone, fillAnimation = _a.fillAnimation, fillDirection = _a.fillDirection, fillTextColor = _a.fillTextColor, outlineSize = _a.outlineSize, isLoading = _a.isLoading, status = _a.status, children = _a.children, bold = _a.bold, style = _a.style, onClick = _a.onClick, rest = __rest(_a, ["variant", "color", "bg", "funcss", "startIcon", "endIcon", "text", "rounded", "raised", "height", "width", "float", "hoverUp", "fullWidth", "outlined", "small", "hoverless", "smaller", "big", "bigger", "jumbo", "flat", "hoverNone", "fillAnimation", "fillDirection", "fillTextColor", "outlineSize", "isLoading", "status", "children", "bold", "style", "onClick"]);
35
+ // Use the component config hook
36
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Button', variant).mergeWithLocal;
37
+ // Merge config with local props - local props should override config
38
+ var mergedProps = mergeWithLocal(__assign({ color: color, bg: bg, funcss: funcss, text: text, rounded: rounded, raised: raised, height: height, width: width, float: float, hoverUp: hoverUp, fullWidth: fullWidth, outlined: outlined, small: small, hoverless: hoverless, smaller: smaller, big: big, bigger: bigger, jumbo: jumbo, flat: flat, hoverNone: hoverNone, fillAnimation: fillAnimation, fillDirection: fillDirection, fillTextColor: fillTextColor, outlineSize: outlineSize, isLoading: isLoading, status: status, bold: bold }, rest)).props;
39
+ // Use mergedProps directly instead of getProp - this ensures local props override config
40
+ var finalIsLoading = mergedProps.isLoading;
41
+ var finalStatus = mergedProps.status;
42
+ var finalText = mergedProps.text;
43
+ var finalOutlined = mergedProps.outlined;
44
+ var finalBg = mergedProps.bg;
45
+ var finalColor = mergedProps.color;
46
+ var finalRounded = mergedProps.rounded;
47
+ var finalHoverless = mergedProps.hoverless;
48
+ var finalBold = mergedProps.bold;
49
+ var finalFloat = mergedProps.float;
50
+ var finalRaised = mergedProps.raised;
51
+ var finalHoverUp = mergedProps.hoverUp;
52
+ var finalFlat = mergedProps.flat;
53
+ var finalHoverNone = mergedProps.hoverNone;
54
+ var finalSmall = mergedProps.small;
55
+ var finalSmaller = mergedProps.smaller;
56
+ var finalBig = mergedProps.big;
57
+ var finalBigger = mergedProps.bigger;
58
+ var finalJumbo = mergedProps.jumbo;
59
+ var finalFillAnimation = mergedProps.fillAnimation;
60
+ var finalFillDirection = mergedProps.fillDirection;
61
+ var finalFillTextColor = mergedProps.fillTextColor;
62
+ var finalFuncss = mergedProps.funcss;
64
63
  function removeNumbers(text) {
64
+ if (!text)
65
+ return '';
65
66
  return text.replace(/[0-9]/g, '');
66
67
  }
67
68
  function hasNumberAbove(text) {
68
- var matches = text.match(/\d+/g); // find all numbers in the string
69
+ if (!text)
70
+ return false;
71
+ var matches = text.match(/\d+/g);
69
72
  if (!matches)
70
73
  return false;
71
74
  return matches.some(function (num) { return parseInt(num) >= 400; });
72
75
  }
73
76
  function hasNumber(text) {
77
+ if (!text)
78
+ return false;
74
79
  return /\d/.test(text);
75
80
  }
81
+ // Determine text color class using final values (local props override config)
82
+ var textColorClass = finalBg ?
83
+ finalColor ?
84
+ finalColor :
85
+ !hasNumber(finalBg) && !finalOutlined ?
86
+ "" :
87
+ hasNumberAbove(finalBg) && !finalOutlined ?
88
+ "white" :
89
+ removeNumbers(finalBg)
90
+ : finalColor;
76
91
  var classNames = [
77
92
  'button',
78
- "text-".concat(bg ? color ? color : !hasNumber(bg) && !outlined ? "" : hasNumberAbove(bg) && !outlined ? "white" : removeNumbers(bg) : color),
79
- funcss || '',
80
- rounded ? 'roundBtn' : '',
81
- hoverless ? 'hoverless' : '',
82
- bold ? 'text-bold' : '',
83
- float ? 'floatBtn' : '',
84
- raised ? 'raisedBtn' : '',
85
- hoverUp ? 'hover-up' : '',
86
- flat ? 'flat' : '',
87
- hoverNone ? 'hoverNone' : '',
88
- small ? 'smallBtn' :
89
- smaller ? 'smallerBtn' : '',
90
- big ? 'bigBtn' : '',
91
- bigger ? 'biggerBtn' : '',
92
- jumbo ? 'jumboBtn' : '',
93
- outlined ? "outlined outline-".concat(bg || '', " text-").concat(color ? color : removeNumbers(bg)) : bg || '',
94
- "".concat(fillAnimation ? "".concat(fillTextColor ? "hover-text-".concat(fillTextColor) : '', " button-fill fill-").concat(fillDirection ? fillDirection : 'left') : '')
93
+ "text-".concat(textColorClass),
94
+ finalFuncss || '',
95
+ finalRounded ? 'roundBtn' : '',
96
+ finalHoverless ? 'hoverless' : '',
97
+ finalBold ? 'text-bold' : '',
98
+ finalFloat ? 'floatBtn' : '',
99
+ finalRaised ? 'raisedBtn' : '',
100
+ finalHoverUp ? 'hover-up' : '',
101
+ finalFlat ? 'flat' : '',
102
+ finalHoverNone ? 'hoverNone' : '',
103
+ finalSmall ? 'smallBtn' :
104
+ finalSmaller ? 'smallerBtn' : '',
105
+ finalBig ? 'bigBtn' : '',
106
+ finalBigger ? 'biggerBtn' : '',
107
+ finalJumbo ? 'jumboBtn' : '',
108
+ finalOutlined ? "outlined outline-".concat(finalBg || '', " text-").concat(finalColor ? finalColor : removeNumbers(finalBg)) : finalBg || '',
109
+ "".concat(finalFillAnimation ? "".concat(finalFillTextColor ? "hover-text-".concat(finalFillTextColor) : '', " button-fill fill-").concat(finalFillDirection || 'left') : '')
95
110
  ].join(' ');
96
- return (React.createElement("span", null,
97
- React.createElement("button", __assign({ className: "".concat(classNames, " ").concat(startIcon || endIcon || status || isLoading ? 'iconic' : ''), style: __assign({ height: height || '', width: fullWidth ? '100%' : width || '', borderRadius: flat ? '0rem' : '' }, style), onClick: onClick }, rest),
98
- isLoading &&
99
- React.createElement("span", { className: 'rotate btn_left_icon', style: { lineHeight: "0" } },
100
- React.createElement(pi_1.PiSpinner, null)),
101
- status &&
102
- React.createElement("span", { className: ' btn_left_icon', style: { lineHeight: "0" } },
103
- status === "success" && React.createElement(pi_1.PiCheck, null),
104
- status === "info" && React.createElement(pi_1.PiInfo, null),
105
- status === "warning" && React.createElement(pi_1.PiWarning, null),
106
- status === "danger" && React.createElement(pi_1.PiX, null)),
107
- fillAnimation ? React.createElement("span", { className: "button_fill_span ".concat(bg) }) : '',
108
- startIcon && React.createElement("span", { className: "btn_left_icon", style: { lineHeight: "0" } }, startIcon),
109
- text ? text : children,
110
- endIcon && React.createElement("span", { className: "btn_right_icon", style: { lineHeight: "0" } }, endIcon))));
111
+ return (react_1.default.createElement("span", null,
112
+ react_1.default.createElement("button", __assign({ className: "".concat(classNames, " ").concat(startIcon || endIcon || finalStatus || finalIsLoading ? 'iconic' : ''), style: __assign({ height: mergedProps.height || '', width: mergedProps.fullWidth ? '100%' : mergedProps.width || '', borderRadius: finalFlat ? '0rem' : '' }, style), onClick: onClick }, mergedProps),
113
+ finalIsLoading && (react_1.default.createElement("span", { className: 'rotate btn_left_icon', style: { lineHeight: "0" } },
114
+ react_1.default.createElement(pi_1.PiSpinner, null))),
115
+ finalStatus && (react_1.default.createElement("span", { className: 'btn_left_icon', style: { lineHeight: "0" } },
116
+ finalStatus === "success" && react_1.default.createElement(pi_1.PiCheck, null),
117
+ finalStatus === "info" && react_1.default.createElement(pi_1.PiInfo, null),
118
+ finalStatus === "warning" && react_1.default.createElement(pi_1.PiWarning, null),
119
+ finalStatus === "danger" && react_1.default.createElement(pi_1.PiX, null))),
120
+ finalFillAnimation && react_1.default.createElement("span", { className: "button_fill_span ".concat(finalBg) }),
121
+ startIcon && react_1.default.createElement("span", { className: "btn_left_icon", style: { lineHeight: "0" } }, startIcon),
122
+ finalText ? finalText : children,
123
+ endIcon && react_1.default.createElement("span", { className: "btn_right_icon", style: { lineHeight: "0" } }, endIcon))));
111
124
  }
@@ -18,6 +18,7 @@ interface BaseInputProps {
18
18
  startIcon?: React.ReactNode;
19
19
  endIcon?: React.ReactNode;
20
20
  iconicBg?: string;
21
+ variant?: string;
21
22
  }
22
23
  interface SelectOption {
23
24
  value: string;
package/ui/input/Input.js CHANGED
@@ -64,6 +64,7 @@ var react_1 = __importStar(require("react"));
64
64
  var pi_1 = require("react-icons/pi");
65
65
  var Button_1 = __importDefault(require("../button/Button"));
66
66
  var theme_1 = require("../theme/theme");
67
+ var componentUtils_1 = require("../../utils/componentUtils");
67
68
  // Utility function to generate CSS classes
68
69
  var generateInputClasses = function (_a) {
69
70
  var status = _a.status, rounded = _a.rounded, bg = _a.bg, funcss = _a.funcss, flat = _a.flat, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, bordered = _a.bordered, borderless = _a.borderless, _b = _a.additionalClasses, additionalClasses = _b === void 0 ? '' : _b;
@@ -91,65 +92,81 @@ var IconicInputWrapper = function (_a) {
91
92
  };
92
93
  // Text Input Component
93
94
  var TextInput = function (_a) {
94
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, _b = _a.fullWidth, fullWidth = _b === void 0 ? true : _b, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _c = _a.type, type = _c === void 0 ? 'text' : _c, label = _a.label, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "type", "label"]);
95
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, _b = _a.fullWidth, fullWidth = _b === void 0 ? true : _b, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _c = _a.type, type = _c === void 0 ? 'text' : _c, label = _a.label, _d = _a.variant, variant = _d === void 0 ? '' : _d, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "type", "label", "variant"]);
96
+ // Use the component config hook
97
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
98
+ // Merge config with local props - local props should override config
99
+ var mergedProps = mergeWithLocal(__assign({ status: status, funcss: funcss, bg: bg, fullWidth: fullWidth, flat: flat, bordered: bordered, borderless: borderless, rounded: rounded, leftRounded: leftRounded, rightRounded: rightRounded, startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg }, rest)).props;
95
100
  var className = generateInputClasses({
96
- status: status,
97
- rounded: rounded,
98
- bg: bg,
99
- funcss: funcss,
100
- flat: flat,
101
- leftRounded: leftRounded,
102
- rightRounded: rightRounded,
103
- bordered: bordered,
104
- borderless: borderless
101
+ status: mergedProps.status,
102
+ rounded: mergedProps.rounded,
103
+ bg: mergedProps.bg,
104
+ funcss: mergedProps.funcss,
105
+ flat: mergedProps.flat,
106
+ leftRounded: mergedProps.leftRounded,
107
+ rightRounded: mergedProps.rightRounded,
108
+ bordered: mergedProps.bordered,
109
+ borderless: mergedProps.borderless
105
110
  });
106
- var style = fullWidth ? { width: '100%' } : undefined;
107
- var inputElement = (react_1.default.createElement("input", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, type: type, placeholder: label, style: style, value: value }, rest)));
108
- return (react_1.default.createElement(IconicInputWrapper, { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, funcss: funcss }, inputElement));
111
+ var style = mergedProps.fullWidth ? { width: '100%' } : undefined;
112
+ var inputElement = (react_1.default.createElement("input", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, type: type, placeholder: label, style: style, value: value }, mergedProps)));
113
+ return (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, inputElement));
109
114
  };
110
115
  exports.TextInput = TextInput;
111
116
  // Select Component
112
117
  var SelectInput = function (_a) {
113
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _b = _a.options, options = _b === void 0 ? [] : _b, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "options"]);
118
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _b = _a.options, options = _b === void 0 ? [] : _b, _c = _a.variant, variant = _c === void 0 ? '' : _c, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "options", "variant"]);
119
+ // Use the component config hook
120
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
121
+ // Merge config with local props - local props should override config
122
+ var mergedProps = mergeWithLocal(__assign({ status: status, funcss: funcss, bg: bg, fullWidth: fullWidth, flat: flat, bordered: bordered, borderless: borderless, rounded: rounded, leftRounded: leftRounded, rightRounded: rightRounded, startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg }, rest)).props;
114
123
  var className = generateInputClasses({
115
- status: status,
116
- rounded: rounded,
117
- bg: bg,
118
- funcss: funcss,
119
- flat: flat,
120
- leftRounded: leftRounded,
121
- rightRounded: rightRounded,
122
- bordered: bordered,
123
- borderless: borderless
124
+ status: mergedProps.status,
125
+ rounded: mergedProps.rounded,
126
+ bg: mergedProps.bg,
127
+ funcss: mergedProps.funcss,
128
+ flat: mergedProps.flat,
129
+ leftRounded: mergedProps.leftRounded,
130
+ rightRounded: mergedProps.rightRounded,
131
+ bordered: mergedProps.bordered,
132
+ borderless: mergedProps.borderless
124
133
  });
125
- var style = fullWidth ? { width: '100%' } : undefined;
126
- var selectElement = (react_1.default.createElement("select", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, value: value, style: style }, rest), options.map(function (option) { return (react_1.default.createElement("option", { key: option.value, value: option.value }, option.text)); })));
127
- return (react_1.default.createElement(IconicInputWrapper, { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, funcss: funcss }, selectElement));
134
+ var style = mergedProps.fullWidth ? { width: '100%' } : undefined;
135
+ var selectElement = (react_1.default.createElement("select", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, value: value, style: style }, mergedProps), options.map(function (option) { return (react_1.default.createElement("option", { key: option.value, value: option.value }, option.text)); })));
136
+ return (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, selectElement));
128
137
  };
129
138
  exports.SelectInput = SelectInput;
130
139
  // Textarea Component
131
140
  var TextareaInput = function (_a) {
132
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, label = _a.label, _b = _a.rows, rows = _b === void 0 ? 2 : _b, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "label", "rows"]);
141
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, label = _a.label, _b = _a.rows, rows = _b === void 0 ? 2 : _b, _c = _a.variant, variant = _c === void 0 ? '' : _c, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "label", "rows", "variant"]);
142
+ // Use the component config hook
143
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
144
+ // Merge config with local props - local props should override config
145
+ var mergedProps = mergeWithLocal(__assign({ status: status, funcss: funcss, bg: bg, fullWidth: fullWidth, flat: flat, bordered: bordered, borderless: borderless, rounded: rounded, leftRounded: leftRounded, rightRounded: rightRounded, startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg }, rest)).props;
133
146
  var className = generateInputClasses({
134
- status: status,
135
- rounded: rounded,
136
- bg: bg,
137
- funcss: funcss,
138
- flat: flat,
139
- leftRounded: leftRounded,
140
- rightRounded: rightRounded,
141
- bordered: bordered,
142
- borderless: borderless
147
+ status: mergedProps.status,
148
+ rounded: mergedProps.rounded,
149
+ bg: mergedProps.bg,
150
+ funcss: mergedProps.funcss,
151
+ flat: mergedProps.flat,
152
+ leftRounded: mergedProps.leftRounded,
153
+ rightRounded: mergedProps.rightRounded,
154
+ bordered: mergedProps.bordered,
155
+ borderless: mergedProps.borderless
143
156
  });
144
- var style = fullWidth ? { width: '100%' } : undefined;
145
- var textareaElement = (react_1.default.createElement("textarea", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, placeholder: label, style: style, value: value, rows: rows }, rest)));
146
- return (react_1.default.createElement(IconicInputWrapper, { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, funcss: funcss }, textareaElement));
157
+ var style = mergedProps.fullWidth ? { width: '100%' } : undefined;
158
+ var textareaElement = (react_1.default.createElement("textarea", __assign({ id: id, name: name, className: className, onChange: onChange, defaultValue: defaultValue, placeholder: label, style: style, value: value, rows: rows }, mergedProps)));
159
+ return (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, textareaElement));
147
160
  };
148
161
  exports.TextareaInput = TextareaInput;
149
162
  // File Input Component
150
163
  var FileInput = function (_a) {
151
- var _b = _a.id, id = _b === void 0 ? 'fileInput' : _b, name = _a.name, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _c = _a.label, label = _c === void 0 ? 'Upload File' : _c, icon = _a.icon, extra = _a.extra, button = _a.button, btn = _a.btn, value = _a.value, rest = __rest(_a, ["id", "name", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "label", "icon", "extra", "button", "btn", "value"]);
152
- var _d = (0, react_1.useState)(''), fileName = _d[0], setFileName = _d[1];
164
+ var _b = _a.id, id = _b === void 0 ? 'fileInput' : _b, name = _a.name, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _c = _a.label, label = _c === void 0 ? 'Upload File' : _c, icon = _a.icon, extra = _a.extra, button = _a.button, btn = _a.btn, value = _a.value, _d = _a.variant, variant = _d === void 0 ? '' : _d, rest = __rest(_a, ["id", "name", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "iconicBg", "label", "icon", "extra", "button", "btn", "value", "variant"]);
165
+ var _e = (0, react_1.useState)(''), fileName = _e[0], setFileName = _e[1];
166
+ // Use the component config hook
167
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
168
+ // Merge config with local props - local props should override config
169
+ var mergedProps = mergeWithLocal(__assign({ status: status, funcss: funcss, bg: bg, fullWidth: fullWidth, flat: flat, rounded: rounded, leftRounded: leftRounded, rightRounded: rightRounded, startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg }, rest)).props;
153
170
  var handleChange = function (e) {
154
171
  var _a;
155
172
  var file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
@@ -161,22 +178,22 @@ var FileInput = function (_a) {
161
178
  };
162
179
  if (btn) {
163
180
  var className = generateInputClasses({
164
- status: status,
165
- rounded: rounded,
166
- bg: bg,
167
- funcss: funcss,
168
- flat: flat,
169
- leftRounded: leftRounded,
170
- rightRounded: rightRounded,
181
+ status: mergedProps.status,
182
+ rounded: mergedProps.rounded,
183
+ bg: mergedProps.bg,
184
+ funcss: mergedProps.funcss,
185
+ flat: mergedProps.flat,
186
+ leftRounded: mergedProps.leftRounded,
187
+ rightRounded: mergedProps.rightRounded,
171
188
  bordered: true,
172
189
  borderless: false,
173
190
  additionalClasses: 'filedInput'
174
191
  });
175
- var style = fullWidth ? { width: '100%' } : undefined;
192
+ var style = mergedProps.fullWidth ? { width: '100%' } : undefined;
176
193
  var fileInputElement = (react_1.default.createElement("div", { className: "fileInput" },
177
- button || (react_1.default.createElement(Button_1.default, { funcss: funcss, startIcon: icon || react_1.default.createElement(pi_1.PiCloudArrowUp, null), bg: "primary", fullWidth: true, raised: true }, fileName || label)),
178
- react_1.default.createElement("input", __assign({ id: id, name: name, className: className, onChange: handleChange, type: "file", style: style, value: value }, rest))));
179
- return (react_1.default.createElement(IconicInputWrapper, { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, funcss: funcss }, fileInputElement));
194
+ button || (react_1.default.createElement(Button_1.default, { funcss: mergedProps.funcss, startIcon: icon || react_1.default.createElement(pi_1.PiCloudArrowUp, null), bg: "primary", fullWidth: true, raised: true }, fileName || label)),
195
+ react_1.default.createElement("input", __assign({ id: id, name: name, className: className, onChange: handleChange, type: "file", style: style, value: value }, mergedProps))));
196
+ return (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, fileInputElement));
180
197
  }
181
198
  var uploadElement = (react_1.default.createElement("div", { className: "_upload_container" },
182
199
  react_1.default.createElement("label", { htmlFor: id, className: "_upload_label" },
@@ -189,15 +206,19 @@ var FileInput = function (_a) {
189
206
  width: '100%',
190
207
  } }, fileName || label),
191
208
  extra && react_1.default.createElement("div", { className: "text-small opacity-3" }, extra)),
192
- react_1.default.createElement("input", __assign({ onChange: handleChange, type: "file", id: id, className: "_upload_input" }, rest))));
193
- return (react_1.default.createElement(IconicInputWrapper, { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, funcss: funcss }, uploadElement));
209
+ react_1.default.createElement("input", __assign({ onChange: handleChange, type: "file", id: id, className: "_upload_input" }, mergedProps))));
210
+ return (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, uploadElement));
194
211
  };
195
212
  exports.FileInput = FileInput;
196
213
  var Input = function (_a) {
197
- var select = _a.select, multiline = _a.multiline, file = _a.file, noBorder = _a.noBorder, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, props = __rest(_a, ["select", "multiline", "file", "noBorder", "startIcon", "endIcon", "iconicBg"]);
198
- // Handle legacy noBorder prop
199
- var variant = (0, theme_1.useVariant)().variant;
200
- var inputProps = __assign(__assign({}, props), { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg, bordered: variant === 'standard' ? true : props.bordered, borderless: variant === 'minimal' ? true : noBorder || props.borderless });
214
+ var select = _a.select, multiline = _a.multiline, file = _a.file, noBorder = _a.noBorder, startIcon = _a.startIcon, endIcon = _a.endIcon, iconicBg = _a.iconicBg, _b = _a.variant, variant = _b === void 0 ? '' : _b, props = __rest(_a, ["select", "multiline", "file", "noBorder", "startIcon", "endIcon", "iconicBg", "variant"]);
215
+ // Use the component config hook for the main Input component
216
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
217
+ // Merge config with local props
218
+ var mergedProps = mergeWithLocal(__assign(__assign({}, props), { startIcon: startIcon, endIcon: endIcon, iconicBg: iconicBg })).props;
219
+ // Handle legacy noBorder prop and theme variant
220
+ var themeVariant = (0, theme_1.useVariant)().variant;
221
+ var inputProps = __assign(__assign({}, mergedProps), { variant: variant, bordered: themeVariant === 'standard' ? true : mergedProps.bordered, borderless: themeVariant === 'minimal' ? true : noBorder || mergedProps.borderless });
201
222
  if (select) {
202
223
  return react_1.default.createElement(exports.SelectInput, __assign({}, inputProps));
203
224
  }
@@ -10,8 +10,13 @@ interface CustomSelectProps {
10
10
  defaultValue?: string;
11
11
  placeholder?: string;
12
12
  options: SelectOption[];
13
- onChange?: (value: string, option: SelectOption) => void;
14
- onBlur?: (event: React.FocusEvent) => void;
13
+ onChange?: (value: string, event?: {
14
+ target: {
15
+ value: string;
16
+ name: string;
17
+ };
18
+ }) => void;
19
+ onBlur?: (event: React.FocusEvent<HTMLSelectElement>) => void;
15
20
  searchable?: boolean;
16
21
  disabled?: boolean;
17
22
  bordered?: boolean;
@@ -25,6 +30,7 @@ interface CustomSelectProps {
25
30
  label?: string;
26
31
  searchAutoFocus?: boolean;
27
32
  style?: React.CSSProperties;
33
+ required?: boolean;
28
34
  }
29
35
  declare const Select: React.FC<CustomSelectProps>;
30
36
  export default Select;
@@ -36,26 +36,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  var react_1 = __importStar(require("react"));
37
37
  var theme_1 = require("../theme/theme");
38
38
  var Select = function (_a) {
39
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, _b = _a.label, label = _b === void 0 ? 'Select an option' : _b, _c = _a.options, options = _c === void 0 ? [] : _c, onChange = _a.onChange, onBlur = _a.onBlur, _d = _a.searchable, searchable = _d === void 0 ? true : _d, _e = _a.disabled, disabled = _e === void 0 ? false : _e, _f = _a.bordered, bordered = _f === void 0 ? false : _f, _g = _a.borderless, borderless = _g === void 0 ? false : _g, _h = _a.rounded, rounded = _h === void 0 ? false : _h, _j = _a.flat, flat = _j === void 0 ? false : _j, _k = _a.fullWidth, fullWidth = _k === void 0 ? false : _k, _l = _a.status, status = _l === void 0 ? '' : _l, _m = _a.className, className = _m === void 0 ? '' : _m, _o = _a.funcss, funcss = _o === void 0 ? '' : _o, _p = _a.style, style = _p === void 0 ? {} : _p, _q = _a.searchAutoFocus, searchAutoFocus = _q === void 0 ? false : _q;
40
- var _r = (0, react_1.useState)(false), isOpen = _r[0], setIsOpen = _r[1];
41
- var _s = (0, react_1.useState)(null), selectedOption = _s[0], setSelectedOption = _s[1];
39
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, _b = _a.label, label = _b === void 0 ? 'Select an option' : _b, _c = _a.options, options = _c === void 0 ? [] : _c, onChange = _a.onChange, onBlur = _a.onBlur, _d = _a.searchable, searchable = _d === void 0 ? true : _d, _e = _a.disabled, disabled = _e === void 0 ? false : _e, _f = _a.bordered, bordered = _f === void 0 ? false : _f, _g = _a.borderless, borderless = _g === void 0 ? false : _g, _h = _a.rounded, rounded = _h === void 0 ? false : _h, _j = _a.flat, flat = _j === void 0 ? false : _j, _k = _a.fullWidth, fullWidth = _k === void 0 ? false : _k, _l = _a.status, status = _l === void 0 ? '' : _l, _m = _a.className, className = _m === void 0 ? '' : _m, _o = _a.funcss, funcss = _o === void 0 ? '' : _o, _p = _a.style, style = _p === void 0 ? {} : _p, _q = _a.searchAutoFocus, searchAutoFocus = _q === void 0 ? false : _q, _r = _a.required, required = _r === void 0 ? false : _r;
40
+ var _s = (0, react_1.useState)(false), isOpen = _s[0], setIsOpen = _s[1];
42
41
  var _t = (0, react_1.useState)(''), searchQuery = _t[0], setSearchQuery = _t[1];
43
42
  var _u = (0, react_1.useState)(-1), focusedIndex = _u[0], setFocusedIndex = _u[1];
44
43
  var _v = (0, react_1.useState)(options), filteredOptions = _v[0], setFilteredOptions = _v[1];
44
+ var _w = (0, react_1.useState)(value || defaultValue || ''), internalValue = _w[0], setInternalValue = _w[1];
45
45
  var containerRef = (0, react_1.useRef)(null);
46
46
  var triggerRef = (0, react_1.useRef)(null);
47
47
  var searchInputRef = (0, react_1.useRef)(null);
48
+ var selectRef = (0, react_1.useRef)(null);
48
49
  var variant = (0, theme_1.useVariant)().variant;
49
- // Initialize selected option
50
- (0, react_1.useEffect)(function () {
51
- var initialValue = value || defaultValue;
52
- if (initialValue) {
53
- var option = options.find(function (opt) { return opt.value === initialValue; });
54
- if (option) {
55
- setSelectedOption(option);
56
- }
57
- }
58
- }, [value, defaultValue, options]);
50
+ var currentValue = value !== undefined ? value : internalValue;
51
+ var selectedOption = options.find(function (opt) { return opt.value === currentValue; }) || null;
59
52
  // Update filtered options when search query changes
60
53
  (0, react_1.useEffect)(function () {
61
54
  if (searchQuery) {
@@ -105,9 +98,32 @@ var Select = function (_a) {
105
98
  setFocusedIndex(-1);
106
99
  };
107
100
  var selectOption = function (option) {
108
- setSelectedOption(option);
101
+ setInternalValue(option.value);
109
102
  closeDropdown();
110
- onChange === null || onChange === void 0 ? void 0 : onChange(option.value, option);
103
+ // Trigger native select change
104
+ if (selectRef.current) {
105
+ selectRef.current.value = option.value;
106
+ var nativeEvent = new Event('change', { bubbles: true });
107
+ selectRef.current.dispatchEvent(nativeEvent);
108
+ }
109
+ // Call onChange with value as first argument and event object as second
110
+ if (onChange) {
111
+ var eventObject = {
112
+ target: { value: option.value, name: name || '' }
113
+ };
114
+ onChange(option.value, eventObject);
115
+ }
116
+ };
117
+ var handleNativeChange = function (event) {
118
+ var newValue = event.target.value;
119
+ var option = options.find(function (opt) { return opt.value === newValue; });
120
+ setInternalValue(newValue);
121
+ if (onChange && option) {
122
+ var eventObject = {
123
+ target: { value: newValue, name: name || '' }
124
+ };
125
+ onChange(newValue, eventObject);
126
+ }
111
127
  };
112
128
  var handleKeyDown = function (event) {
113
129
  var _a;
@@ -175,11 +191,20 @@ var Select = function (_a) {
175
191
  var classes = [
176
192
  'custom-select',
177
193
  fullWidth && 'fullWidth',
178
- ,
194
+ className,
179
195
  ].filter(Boolean);
180
196
  return classes.join(' ');
181
197
  };
182
198
  return (react_1.default.createElement("div", { ref: containerRef, className: "".concat(funcss, " ").concat(rounded && 'round-edge', " ").concat(getContainerClasses()), style: style },
199
+ react_1.default.createElement("select", { ref: selectRef, id: id, name: name, value: currentValue, onChange: handleNativeChange, onBlur: onBlur, disabled: disabled, required: required, style: {
200
+ position: 'absolute',
201
+ opacity: 0,
202
+ width: 0,
203
+ height: 0,
204
+ pointerEvents: 'none'
205
+ }, tabIndex: -1 },
206
+ !label && react_1.default.createElement("option", { value: "" }, "Select an option"),
207
+ options.map(function (option) { return (react_1.default.createElement("option", { key: option.value, value: option.value }, option.text)); })),
183
208
  react_1.default.createElement("div", { ref: triggerRef, className: "".concat(funcss, " ").concat(rounded && 'round-edge', " ").concat(getTriggerClasses()), onClick: openDropdown, onKeyDown: handleKeyDown, tabIndex: disabled ? -1 : 0, role: "button", "aria-expanded": isOpen, "aria-haspopup": "listbox" },
184
209
  react_1.default.createElement("span", { className: "select-value ".concat(!selectedOption ? 'select-placeholder' : '') }, selectedOption ? selectedOption.text : label),
185
210
  react_1.default.createElement("div", { className: "select-arrow ".concat(isOpen ? 'open' : '') },
@@ -187,7 +212,6 @@ var Select = function (_a) {
187
212
  react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" })))),
188
213
  react_1.default.createElement("div", { className: "select-dropdown ".concat(isOpen ? 'open' : '', " ") },
189
214
  searchable && (react_1.default.createElement("input", { ref: searchInputRef, type: "text", className: "select-search", placeholder: "Search options...", value: searchQuery, onChange: function (e) { return setSearchQuery(e.target.value); }, onKeyDown: handleSearchKeyDown })),
190
- react_1.default.createElement("div", { className: "select-options", role: "listbox" }, filteredOptions.length === 0 ? (react_1.default.createElement("div", { className: "select-option no-results" }, "No options found")) : (filteredOptions.map(function (option, index) { return (react_1.default.createElement("button", { key: option.value, type: "button", className: "select-option ".concat((selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) === option.value ? 'selected' : '', " ").concat(index === focusedIndex ? 'focused' : ''), onClick: function () { return selectOption(option); }, role: "option", "aria-selected": (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) === option.value }, option.text)); })))),
191
- react_1.default.createElement("input", { type: "hidden", id: id, name: name, value: (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) || '' })));
215
+ react_1.default.createElement("div", { className: "select-options", role: "listbox" }, filteredOptions.length === 0 ? (react_1.default.createElement("div", { className: "select-option no-results" }, "No options found")) : (filteredOptions.map(function (option, index) { return (react_1.default.createElement("button", { key: option.value, type: "button", className: "select-option ".concat((selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) === option.value ? 'selected' : '', " ").concat(index === focusedIndex ? 'focused' : ''), onClick: function () { return selectOption(option); }, role: "option", "aria-selected": (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) === option.value }, option.text)); }))))));
192
216
  };
193
217
  exports.default = Select;
package/ui/text/Text.d.ts CHANGED
@@ -39,6 +39,7 @@ type TypographyProps = {
39
39
  customStyles?: React.CSSProperties;
40
40
  onClick?: () => void;
41
41
  children?: React.ReactNode;
42
+ variant?: string;
42
43
  size?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "7xl" | "8xl" | "9xl" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
43
44
  };
44
45
  declare const Text: React.FC<TypographyProps>;
package/ui/text/Text.js CHANGED
@@ -28,52 +28,56 @@ Object.defineProperty(exports, "__esModule", { value: true });
28
28
  var react_1 = __importDefault(require("react"));
29
29
  var pi_1 = require("react-icons/pi");
30
30
  var getCssVariable_1 = require("../../utils/getCssVariable");
31
+ var componentUtils_1 = require("../../utils/componentUtils");
31
32
  var Text = function (_a) {
32
- var id = _a.id, bg = _a.bg, color = _a.color, children = _a.children, hoverBg = _a.hoverBg, hoverText = _a.hoverText, text = _a.text, funcss = _a.funcss, emp = _a.emp, bold = _a.bold, block = _a.block, body = _a.body, article = _a.article, light = _a.light, lighter = _a.lighter, italic = _a.italic, weight = _a.weight, underline = _a.underline, align = _a.align, lineHeight = _a.lineHeight, letterSpacing = _a.letterSpacing, uppercase = _a.uppercase, lowercase = _a.lowercase, capitalize = _a.capitalize, textDecoration = _a.textDecoration, textTransform = _a.textTransform, whiteSpace = _a.whiteSpace, wordBreak = _a.wordBreak, fontFamily = _a.fontFamily, truncate = _a.truncate, textShadow = _a.textShadow, textAlign = _a.textAlign, customStyles = _a.customStyles, monospace = _a.monospace, quote = _a.quote, opacity = _a.opacity, _b = _a.size, size = _b === void 0 ? 'base' : _b, // default
33
- rest = __rest(_a, ["id", "bg", "color", "children", "hoverBg", "hoverText", "text", "funcss", "emp", "bold", "block", "body", "article", "light", "lighter", "italic", "weight", "underline", "align", "lineHeight", "letterSpacing", "uppercase", "lowercase", "capitalize", "textDecoration", "textTransform", "whiteSpace", "wordBreak", "fontFamily", "truncate", "textShadow", "textAlign", "customStyles", "monospace", "quote", "opacity", "size"]);
34
- var Tag = block ? 'div' : 'span';
35
- var sizeClass = "".concat(size === 'h1' ? "h1" :
36
- size === 'h2' ? "h2" :
37
- size === 'h3' ? "h3" :
38
- size === 'h4' ? "h4" :
39
- size === 'h5' ? "h5" :
40
- size === 'h6' ? "h6" :
41
- "text-".concat(size));
33
+ var id = _a.id, bg = _a.bg, color = _a.color, children = _a.children, hoverBg = _a.hoverBg, hoverText = _a.hoverText, text = _a.text, funcss = _a.funcss, emp = _a.emp, bold = _a.bold, block = _a.block, body = _a.body, article = _a.article, light = _a.light, lighter = _a.lighter, italic = _a.italic, weight = _a.weight, underline = _a.underline, align = _a.align, lineHeight = _a.lineHeight, letterSpacing = _a.letterSpacing, uppercase = _a.uppercase, lowercase = _a.lowercase, capitalize = _a.capitalize, textDecoration = _a.textDecoration, textTransform = _a.textTransform, whiteSpace = _a.whiteSpace, wordBreak = _a.wordBreak, fontFamily = _a.fontFamily, truncate = _a.truncate, textShadow = _a.textShadow, textAlign = _a.textAlign, customStyles = _a.customStyles, monospace = _a.monospace, quote = _a.quote, opacity = _a.opacity, _b = _a.variant, variant = _b === void 0 ? '' : _b, _c = _a.size, size = _c === void 0 ? 'base' : _c, rest = __rest(_a, ["id", "bg", "color", "children", "hoverBg", "hoverText", "text", "funcss", "emp", "bold", "block", "body", "article", "light", "lighter", "italic", "weight", "underline", "align", "lineHeight", "letterSpacing", "uppercase", "lowercase", "capitalize", "textDecoration", "textTransform", "whiteSpace", "wordBreak", "fontFamily", "truncate", "textShadow", "textAlign", "customStyles", "monospace", "quote", "opacity", "variant", "size"]);
34
+ // Use the component config hook
35
+ var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Text', variant).mergeWithLocal;
36
+ // Merge config with local props - local props override config
37
+ var mergedProps = mergeWithLocal(__assign({ bg: bg, color: color, funcss: funcss, emp: emp, bold: bold, block: block, body: body, article: article, light: light, lighter: lighter, italic: italic, weight: weight, underline: underline, align: align, lineHeight: lineHeight, letterSpacing: letterSpacing, uppercase: uppercase, lowercase: lowercase, capitalize: capitalize, textDecoration: textDecoration, textTransform: textTransform, whiteSpace: whiteSpace, wordBreak: wordBreak, fontFamily: fontFamily, truncate: truncate, textShadow: textShadow, textAlign: textAlign, monospace: monospace, quote: quote, opacity: opacity, size: size }, rest)).props;
38
+ var Tag = mergedProps.block ? 'div' : 'span';
39
+ var sizeClass = "".concat(mergedProps.size === 'h1' ? "h1" :
40
+ mergedProps.size === 'h2' ? "h2" :
41
+ mergedProps.size === 'h3' ? "h3" :
42
+ mergedProps.size === 'h4' ? "h4" :
43
+ mergedProps.size === 'h5' ? "h5" :
44
+ mergedProps.size === 'h6' ? "h6" :
45
+ "text-".concat(mergedProps.size));
42
46
  var bdFontWeight = (0, getCssVariable_1.getCssVariableValue)('bd-font-weight');
43
- var mergedStyles = __assign(__assign({ display: block ? 'block' : undefined, fontWeight: bold ? 'bold' : weight ? weight : Number(bdFontWeight), lineHeight: lineHeight, letterSpacing: letterSpacing, textTransform: textTransform, textDecoration: textDecoration, fontFamily: fontFamily, textShadow: textShadow, textAlign: textAlign, whiteSpace: whiteSpace, wordBreak: wordBreak, transform: customStyles === null || customStyles === void 0 ? void 0 : customStyles.transform }, customStyles), (truncate
47
+ var mergedStyles = __assign(__assign({ display: mergedProps.block ? 'block' : undefined, fontWeight: mergedProps.bold ? 'bold' : mergedProps.weight ? mergedProps.weight : Number(bdFontWeight), lineHeight: mergedProps.lineHeight, letterSpacing: mergedProps.letterSpacing, textTransform: mergedProps.textTransform, textDecoration: mergedProps.textDecoration, fontFamily: mergedProps.fontFamily, textShadow: mergedProps.textShadow, textAlign: mergedProps.textAlign, whiteSpace: mergedProps.whiteSpace, wordBreak: mergedProps.wordBreak, transform: mergedProps.transform }, customStyles), (mergedProps.truncate
44
48
  ? {
45
49
  display: '-webkit-box',
46
50
  WebkitBoxOrient: 'vertical',
47
- WebkitLineClamp: truncate,
51
+ WebkitLineClamp: mergedProps.truncate,
48
52
  overflow: 'hidden',
49
53
  textOverflow: 'ellipsis',
50
54
  }
51
55
  : {}));
52
56
  var classNames = [
53
- funcss || '',
57
+ mergedProps.funcss || '',
54
58
  sizeClass,
55
- color ? " text-".concat(color, " ") : '',
56
- align ? " text-".concat(align, " ") : '',
57
- monospace ? 'monospace' : '',
58
- bg || '',
59
+ mergedProps.color ? " text-".concat(mergedProps.color, " ") : '',
60
+ mergedProps.align ? " text-".concat(mergedProps.align, " ") : '',
61
+ mergedProps.monospace ? 'monospace' : '',
62
+ mergedProps.bg || '',
59
63
  hoverText ? "hover-text-".concat(hoverText) : '',
60
64
  hoverBg ? "hover-".concat(hoverBg) : '',
61
- light ? 'lightText' : lighter ? 'lighterText' : '',
62
- italic ? 'italicText' : '',
63
- underline ? 'underlineText' : '',
64
- body ? 'body' : '',
65
- article ? 'article' : '',
66
- emp ? 'emp' : '',
67
- bold ? 'bold' : '',
68
- uppercase ? 'uppercase' : '',
69
- lowercase ? 'lowercase' : '',
70
- capitalize ? 'capitalize' : '',
71
- opacity ? 'opacity-' + opacity : '',
65
+ mergedProps.light ? 'lightText' : mergedProps.lighter ? 'lighterText' : '',
66
+ mergedProps.italic ? 'italicText' : '',
67
+ mergedProps.underline ? 'underlineText' : '',
68
+ mergedProps.body ? 'body' : '',
69
+ mergedProps.article ? 'article' : '',
70
+ mergedProps.emp ? 'emp' : '',
71
+ mergedProps.bold ? 'bold' : '',
72
+ mergedProps.uppercase ? 'uppercase' : '',
73
+ mergedProps.lowercase ? 'lowercase' : '',
74
+ mergedProps.capitalize ? 'capitalize' : '',
75
+ mergedProps.opacity ? 'opacity-' + mergedProps.opacity : '',
72
76
  ]
73
77
  .filter(Boolean)
74
78
  .join(' ');
75
- return (react_1.default.createElement(Tag, __assign({ id: id, className: classNames, style: mergedStyles }, rest),
76
- quote && (react_1.default.createElement("div", null,
79
+ return (react_1.default.createElement(Tag, __assign({ id: id, className: classNames, style: mergedStyles }, mergedProps),
80
+ mergedProps.quote && (react_1.default.createElement("div", null,
77
81
  react_1.default.createElement(pi_1.PiQuotesLight, null))),
78
82
  children,
79
83
  text));
@@ -1,15 +1,39 @@
1
1
  import React, { ReactNode } from 'react';
2
2
  export type ThemeVariant = 'standard' | 'minimal';
3
3
  export type ThemeName = 'light' | 'dark' | 'dark-blue' | 'light-gray' | 'pastel-green' | 'warm-orange' | 'frosted-glass' | 'midnight-purple' | 'cyber-metal';
4
+ interface ThemeConfig {
5
+ [key: string]: any;
6
+ }
7
+ interface ProjectData {
8
+ theme_config?: ThemeConfig;
9
+ default_variation?: ThemeVariant;
10
+ name?: string;
11
+ colors?: any;
12
+ global?: any;
13
+ components?: any;
14
+ }
4
15
  interface ThemeProviderProps {
5
16
  theme: ThemeName;
6
17
  projectId: string;
7
18
  children: ReactNode;
8
19
  }
9
- interface VariantContextType {
20
+ interface ThemeContextType {
10
21
  variant: ThemeVariant;
11
22
  setVariant: React.Dispatch<React.SetStateAction<ThemeVariant>>;
23
+ themeConfig: ThemeConfig;
24
+ projectData: ProjectData | null;
25
+ isLoading: boolean;
26
+ isInitialLoad: boolean;
27
+ error: string | null;
12
28
  }
13
- export declare const useVariant: () => VariantContextType;
29
+ export declare const useTheme: () => ThemeContextType;
30
+ export declare const useVariant: () => {
31
+ variant: ThemeVariant;
32
+ setVariant: React.Dispatch<React.SetStateAction<ThemeVariant>>;
33
+ };
14
34
  declare const ThemeProvider: React.FC<ThemeProviderProps>;
15
35
  export default ThemeProvider;
36
+ export declare const useThemeValue: (key: string) => string | undefined;
37
+ export declare const useComponentConfig: (componentName: string) => any;
38
+ export declare const useColors: () => any;
39
+ export declare const useGlobalConfig: () => any;
package/ui/theme/theme.js CHANGED
@@ -33,8 +33,44 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
+ return new (P || (P = Promise))(function (resolve, reject) {
39
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
43
+ });
44
+ };
45
+ var __generator = (this && this.__generator) || function (thisArg, body) {
46
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
47
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
+ function verb(n) { return function (v) { return step([n, v]); }; }
49
+ function step(op) {
50
+ if (f) throw new TypeError("Generator is already executing.");
51
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
52
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
53
+ if (y = 0, t) op = [op[0] & 2, t.value];
54
+ switch (op[0]) {
55
+ case 0: case 1: t = op; break;
56
+ case 4: _.label++; return { value: op[1], done: false };
57
+ case 5: _.label++; y = op[1]; op = [0]; continue;
58
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
+ default:
60
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
+ if (t[2]) _.ops.pop();
65
+ _.trys.pop(); continue;
66
+ }
67
+ op = body.call(thisArg, _);
68
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
+ }
71
+ };
36
72
  Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.useVariant = void 0;
73
+ exports.useGlobalConfig = exports.useColors = exports.useComponentConfig = exports.useThemeValue = exports.useVariant = exports.useTheme = void 0;
38
74
  var react_1 = __importStar(require("react"));
39
75
  var themes_1 = require("./themes");
40
76
  var darkenUtils_1 = require("./darkenUtils");
@@ -43,21 +79,124 @@ var db;
43
79
  if (typeof window !== 'undefined') {
44
80
  db = require('../../utils/Firebase').default;
45
81
  }
46
- var VariantContext = (0, react_1.createContext)({
82
+ var ThemeContext = (0, react_1.createContext)({
47
83
  variant: 'standard',
48
- setVariant: function () {
49
- /** noop */
50
- },
84
+ setVariant: function () { },
85
+ themeConfig: {},
86
+ projectData: null,
87
+ isLoading: true,
88
+ isInitialLoad: true,
89
+ error: null,
51
90
  });
52
- var useVariant = function () { return (0, react_1.useContext)(VariantContext); };
91
+ var useTheme = function () {
92
+ var context = (0, react_1.useContext)(ThemeContext);
93
+ if (!context) {
94
+ throw new Error('useTheme must be used within ThemeProvider');
95
+ }
96
+ return context;
97
+ };
98
+ exports.useTheme = useTheme;
99
+ // Backward compatibility
100
+ var useVariant = function () {
101
+ var _a = (0, exports.useTheme)(), variant = _a.variant, setVariant = _a.setVariant;
102
+ return { variant: variant, setVariant: setVariant };
103
+ };
53
104
  exports.useVariant = useVariant;
54
105
  /* -------------------------------------------------------------------------- */
106
+ /* THEME CACHE & STORAGE */
107
+ /* -------------------------------------------------------------------------- */
108
+ var CACHE_KEY = 'funui_theme_cache';
109
+ var CACHE_EXPIRY = 1000 * 60 * 60; // 1 hour
110
+ var getThemeFromCache = function (projectId) {
111
+ if (typeof window === 'undefined')
112
+ return null;
113
+ try {
114
+ var cached = localStorage.getItem("".concat(CACHE_KEY, "_").concat(projectId));
115
+ if (!cached)
116
+ return null;
117
+ var parsed = JSON.parse(cached);
118
+ var isExpired = Date.now() - parsed.timestamp > CACHE_EXPIRY;
119
+ if (isExpired) {
120
+ localStorage.removeItem("".concat(CACHE_KEY, "_").concat(projectId));
121
+ return null;
122
+ }
123
+ return parsed.data;
124
+ }
125
+ catch (error) {
126
+ console.error('Error reading theme cache:', error);
127
+ return null;
128
+ }
129
+ };
130
+ var saveThemeToCache = function (projectId, data) {
131
+ if (typeof window === 'undefined')
132
+ return;
133
+ try {
134
+ var cache = {
135
+ projectId: projectId,
136
+ data: data,
137
+ timestamp: Date.now(),
138
+ };
139
+ localStorage.setItem("".concat(CACHE_KEY, "_").concat(projectId), JSON.stringify(cache));
140
+ }
141
+ catch (error) {
142
+ console.error('Error saving theme cache:', error);
143
+ }
144
+ };
145
+ /* -------------------------------------------------------------------------- */
146
+ /* SINGLETON LISTENER */
147
+ /* -------------------------------------------------------------------------- */
148
+ var activeListener = null;
149
+ var currentProjectId = null;
150
+ var listenerSubscribers = new Set();
151
+ var subscribeToTheme = function (projectId, callback) {
152
+ listenerSubscribers.add(callback);
153
+ // If listener already exists for this project, just subscribe
154
+ if (currentProjectId === projectId && activeListener) {
155
+ return function () {
156
+ listenerSubscribers.delete(callback);
157
+ };
158
+ }
159
+ // Clean up old listener if project changed
160
+ if (activeListener && currentProjectId !== projectId) {
161
+ activeListener();
162
+ activeListener = null;
163
+ currentProjectId = null;
164
+ }
165
+ // Create new listener
166
+ var docRef = (0, firestore_1.doc)(db, 'Projects', projectId);
167
+ currentProjectId = projectId;
168
+ var unsubscribe = (0, firestore_1.onSnapshot)(docRef, function (snapshot) {
169
+ var data = snapshot.data();
170
+ if (!data)
171
+ return;
172
+ // Save to cache
173
+ saveThemeToCache(projectId, data);
174
+ // Notify all subscribers
175
+ listenerSubscribers.forEach(function (cb) { return cb(data); });
176
+ }, function (error) {
177
+ console.error('Theme listener error:', error);
178
+ });
179
+ activeListener = unsubscribe;
180
+ return function () {
181
+ listenerSubscribers.delete(callback);
182
+ if (listenerSubscribers.size === 0 && activeListener) {
183
+ activeListener();
184
+ activeListener = null;
185
+ currentProjectId = null;
186
+ }
187
+ };
188
+ };
189
+ /* -------------------------------------------------------------------------- */
55
190
  /* COMPONENT */
56
191
  /* -------------------------------------------------------------------------- */
57
192
  var ThemeProvider = function (_a) {
58
193
  var theme = _a.theme, children = _a.children, projectId = _a.projectId;
59
194
  var _b = (0, react_1.useState)('standard'), variant = _b[0], setVariant = _b[1];
60
- var _c = (0, react_1.useState)(false), projectLoaded = _c[0], setprojectLoaded = _c[1];
195
+ var _c = (0, react_1.useState)({}), themeConfig = _c[0], setThemeConfig = _c[1];
196
+ var _d = (0, react_1.useState)(null), projectData = _d[0], setProjectData = _d[1];
197
+ var _e = (0, react_1.useState)(true), isLoading = _e[0], setIsLoading = _e[1];
198
+ var _f = (0, react_1.useState)(true), isInitialLoad = _f[0], setIsInitialLoad = _f[1];
199
+ var _g = (0, react_1.useState)(null), error = _g[0], setError = _g[1];
61
200
  /* -------------------------- Apply base theme --------------------------- */
62
201
  (0, react_1.useEffect)(function () {
63
202
  var root = document.documentElement;
@@ -79,39 +218,125 @@ var ThemeProvider = function (_a) {
79
218
  });
80
219
  }
81
220
  }, [theme]);
82
- /* ---------------------- Real-time Firestore sync ----------------------- */
221
+ /* ---------------------- Firebase Theme Sync ----------------------- */
83
222
  (0, react_1.useEffect)(function () {
84
223
  if (typeof window === 'undefined' || !projectId) {
85
- setprojectLoaded(true);
224
+ setIsLoading(false);
225
+ setIsInitialLoad(false);
86
226
  return;
87
227
  }
88
228
  var root = document.documentElement;
89
- var docRef = (0, firestore_1.doc)(db, 'Projects', projectId);
90
- var unsubscribe = (0, firestore_1.onSnapshot)(docRef, function (snapshot) {
91
- var _a;
92
- var data = snapshot.data();
93
- if (!data)
94
- return;
95
- var config = (_a = data.theme_config) !== null && _a !== void 0 ? _a : {};
96
- var newVariant = data.default_variation || 'standard';
97
- setVariant(newVariant);
98
- Object.entries(config).forEach(function (_a) {
99
- var key = _a[0], value = _a[1];
100
- root.style.setProperty(key.startsWith('--') ? key : "--".concat(key), String(value));
229
+ // Step 1: Try to load from cache immediately
230
+ var cachedTheme = getThemeFromCache(projectId);
231
+ if (cachedTheme) {
232
+ applyThemeData(cachedTheme, root);
233
+ setIsLoading(false);
234
+ // Still initialLoad true, but we have cached data to show
235
+ }
236
+ // Step 2: Fetch fresh data (doesn't block render if we have cache)
237
+ var fetchInitialData = function () { return __awaiter(void 0, void 0, void 0, function () {
238
+ var docRef, snapshot, data, err_1;
239
+ return __generator(this, function (_a) {
240
+ switch (_a.label) {
241
+ case 0:
242
+ _a.trys.push([0, 2, 3, 4]);
243
+ docRef = (0, firestore_1.doc)(db, 'Projects', projectId);
244
+ return [4 /*yield*/, (0, firestore_1.getDoc)(docRef)];
245
+ case 1:
246
+ snapshot = _a.sent();
247
+ if (snapshot.exists()) {
248
+ data = snapshot.data();
249
+ applyThemeData(data, root);
250
+ saveThemeToCache(projectId, data);
251
+ }
252
+ return [3 /*break*/, 4];
253
+ case 2:
254
+ err_1 = _a.sent();
255
+ console.error('Error fetching initial theme:', err_1);
256
+ setError('Failed to load theme');
257
+ return [3 /*break*/, 4];
258
+ case 3:
259
+ setIsLoading(false);
260
+ setIsInitialLoad(false);
261
+ return [7 /*endfinally*/];
262
+ case 4: return [2 /*return*/];
263
+ }
101
264
  });
102
- setprojectLoaded(true);
103
- }, function (error) {
104
- console.error('Realtime theme listener error:', error);
105
- setprojectLoaded(true);
265
+ }); };
266
+ // Only fetch if no cache
267
+ if (!cachedTheme) {
268
+ fetchInitialData();
269
+ }
270
+ else {
271
+ // We have cache, mark as loaded after short delay
272
+ setTimeout(function () { return setIsInitialLoad(false); }, 100);
273
+ }
274
+ // Step 3: Subscribe to real-time updates
275
+ var unsubscribe = subscribeToTheme(projectId, function (data) {
276
+ applyThemeData(data, root);
106
277
  });
107
- return function () { return unsubscribe(); };
278
+ return unsubscribe;
108
279
  }, [projectId]);
280
+ /* Helper function to apply theme data */
281
+ var applyThemeData = function (data, root) {
282
+ var _a;
283
+ var config = (_a = data.theme_config) !== null && _a !== void 0 ? _a : {};
284
+ var newVariant = data.default_variation || 'standard';
285
+ setVariant(newVariant);
286
+ setThemeConfig(config);
287
+ setProjectData(data);
288
+ // Apply CSS variables
289
+ Object.entries(config).forEach(function (_a) {
290
+ var key = _a[0], value = _a[1];
291
+ root.style.setProperty(key.startsWith('--') ? key : "--".concat(key), String(value));
292
+ });
293
+ };
294
+ /* Memoize context value to prevent unnecessary re-renders */
295
+ var contextValue = (0, react_1.useMemo)(function () { return ({
296
+ variant: variant,
297
+ setVariant: setVariant,
298
+ themeConfig: themeConfig,
299
+ projectData: projectData,
300
+ isLoading: isLoading,
301
+ isInitialLoad: isInitialLoad,
302
+ error: error,
303
+ }); }, [variant, themeConfig, projectData, isLoading, isInitialLoad, error]);
109
304
  /* ------------------------------- Render ------------------------------- */
110
- return (react_1.default.createElement(VariantContext.Provider, { value: { variant: variant, setVariant: setVariant } },
305
+ return (react_1.default.createElement(ThemeContext.Provider, { value: contextValue },
111
306
  react_1.default.createElement("div", { className: "theme-".concat(theme), style: {
112
307
  backgroundColor: 'var(--page-bg)',
113
308
  color: 'var(--text-color)',
114
309
  minHeight: '100vh',
115
- } }, projectLoaded ? children : "")));
310
+ // Smooth transition when theme changes
311
+ transition: isInitialLoad ? 'none' : 'background-color 0.3s ease, color 0.3s ease',
312
+ } }, children)));
116
313
  };
117
314
  exports.default = ThemeProvider;
315
+ /* -------------------------------------------------------------------------- */
316
+ /* HELPER HOOKS */
317
+ /* -------------------------------------------------------------------------- */
318
+ // Hook to get specific theme values
319
+ var useThemeValue = function (key) {
320
+ var themeConfig = (0, exports.useTheme)().themeConfig;
321
+ return themeConfig[key];
322
+ };
323
+ exports.useThemeValue = useThemeValue;
324
+ // Hook to get component-specific config
325
+ var useComponentConfig = function (componentName) {
326
+ var _a;
327
+ var projectData = (0, exports.useTheme)().projectData;
328
+ return ((_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName]) || {};
329
+ };
330
+ exports.useComponentConfig = useComponentConfig;
331
+ // Hook to get colors
332
+ var useColors = function () {
333
+ var projectData = (0, exports.useTheme)().projectData;
334
+ return (projectData === null || projectData === void 0 ? void 0 : projectData.colors) || {};
335
+ };
336
+ exports.useColors = useColors;
337
+ // Hook to get global config
338
+ var useGlobalConfig = function () {
339
+ var projectData = (0, exports.useTheme)().projectData;
340
+ return (projectData === null || projectData === void 0 ? void 0 : projectData.global) || {};
341
+ };
342
+ exports.useGlobalConfig = useGlobalConfig;
@@ -0,0 +1,48 @@
1
+ export interface ComponentProps {
2
+ [key: string]: any;
3
+ }
4
+ export interface ComponentMetadata {
5
+ createdAt?: Date;
6
+ updatedAt?: Date;
7
+ isCustom?: boolean;
8
+ baseVariant?: string;
9
+ }
10
+ export interface ComponentVariant {
11
+ componentProps: ComponentProps;
12
+ metadata?: ComponentMetadata;
13
+ }
14
+ export interface ComponentConfig {
15
+ componentProps: ComponentProps;
16
+ variantExists: boolean;
17
+ actualVariant: string;
18
+ availableVariants: string[];
19
+ metadata: ComponentMetadata;
20
+ }
21
+ export interface ProjectData {
22
+ components?: {
23
+ [componentName: string]: {
24
+ [variantName: string]: ComponentVariant;
25
+ };
26
+ };
27
+ }
28
+ export interface MergedConfig {
29
+ props: ComponentProps;
30
+ variant: string;
31
+ hasConfig: boolean;
32
+ }
33
+ export interface UseComponentConfigReturn extends ComponentConfig {
34
+ mergeWithLocal: (localProps?: ComponentProps) => MergedConfig;
35
+ getProp: <T = any>(propName: string, defaultValue?: T) => T;
36
+ }
37
+ /**
38
+ * Universal component config getter
39
+ */
40
+ export declare const getComponentConfig: (projectData: ProjectData | null | undefined, componentName: string, variantName?: string) => ComponentConfig;
41
+ /**
42
+ * Merge component config with local props - only applies config if variant exists
43
+ */
44
+ export declare const mergeComponentConfig: (config: ComponentConfig, localProps?: ComponentProps) => MergedConfig;
45
+ /**
46
+ * Hook for easy component config usage - only applies if variant is provided and exists
47
+ */
48
+ export declare const useComponentConfiguration: (componentName: string, variantName?: string) => UseComponentConfigReturn;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.useComponentConfiguration = exports.mergeComponentConfig = exports.getComponentConfig = void 0;
15
+ var theme_1 = require("../ui/theme/theme");
16
+ /**
17
+ * Universal component config getter
18
+ */
19
+ var getComponentConfig = function (projectData, componentName, variantName) {
20
+ var _a;
21
+ if (variantName === void 0) { variantName = 'default'; }
22
+ if (!((_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName])) {
23
+ return {
24
+ componentProps: {},
25
+ variantExists: false,
26
+ actualVariant: variantName,
27
+ availableVariants: [],
28
+ metadata: {}
29
+ };
30
+ }
31
+ var component = projectData.components[componentName];
32
+ var availableVariants = Object.keys(component);
33
+ // Find the best variant match
34
+ var targetVariant = variantName;
35
+ if (!availableVariants.includes(variantName)) {
36
+ if (availableVariants.includes('default')) {
37
+ targetVariant = 'default';
38
+ }
39
+ else if (availableVariants.length > 0) {
40
+ targetVariant = availableVariants[0];
41
+ }
42
+ else {
43
+ return {
44
+ componentProps: {},
45
+ variantExists: false,
46
+ actualVariant: variantName,
47
+ availableVariants: [],
48
+ metadata: {}
49
+ };
50
+ }
51
+ }
52
+ var variantData = component[targetVariant] || {};
53
+ return {
54
+ componentProps: variantData.componentProps || {},
55
+ variantExists: true,
56
+ actualVariant: targetVariant,
57
+ availableVariants: availableVariants,
58
+ metadata: variantData.metadata || {}
59
+ };
60
+ };
61
+ exports.getComponentConfig = getComponentConfig;
62
+ /**
63
+ * Merge component config with local props - only applies config if variant exists
64
+ */
65
+ var mergeComponentConfig = function (config, localProps) {
66
+ if (localProps === void 0) { localProps = {}; }
67
+ // Only apply config if variant exists and has actual configuration
68
+ var hasValidConfig = config.variantExists && Object.keys(config.componentProps).length > 0;
69
+ if (!hasValidConfig) {
70
+ return {
71
+ props: localProps,
72
+ variant: config.actualVariant,
73
+ hasConfig: false
74
+ };
75
+ }
76
+ return {
77
+ // Props: config overrides local only if variant exists
78
+ props: __assign(__assign({}, localProps), config.componentProps),
79
+ // Metadata
80
+ variant: config.actualVariant,
81
+ hasConfig: true
82
+ };
83
+ };
84
+ exports.mergeComponentConfig = mergeComponentConfig;
85
+ /**
86
+ * Hook for easy component config usage - only applies if variant is provided and exists
87
+ */
88
+ var useComponentConfiguration = function (componentName, variantName // Make variantName optional
89
+ ) {
90
+ var projectData = (0, theme_1.useTheme)().projectData;
91
+ // Only get config if variantName is provided
92
+ var config = variantName ? (0, exports.getComponentConfig)(projectData, componentName, variantName) : {
93
+ componentProps: {},
94
+ variantExists: false,
95
+ actualVariant: '',
96
+ availableVariants: [],
97
+ metadata: {}
98
+ };
99
+ var mergeWithLocal = function (localProps) {
100
+ if (localProps === void 0) { localProps = {}; }
101
+ // If no variant name was provided, return local props as-is
102
+ if (!variantName) {
103
+ return {
104
+ props: localProps,
105
+ variant: '',
106
+ hasConfig: false
107
+ };
108
+ }
109
+ return (0, exports.mergeComponentConfig)(config, localProps);
110
+ };
111
+ var getProp = function (propName, defaultValue) { var _a; return ((_a = config.componentProps[propName]) !== null && _a !== void 0 ? _a : defaultValue); };
112
+ return __assign(__assign({}, config), { mergeWithLocal: mergeWithLocal, getProp: getProp });
113
+ };
114
+ exports.useComponentConfiguration = useComponentConfiguration;