funuicss 3.6.6 → 3.6.8
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 +1 -1
- package/ui/button/Button.d.ts +4 -4
- package/ui/button/Button.js +81 -68
- package/ui/input/Input.d.ts +1 -0
- package/ui/input/Input.js +79 -58
- package/ui/select/Select.d.ts +8 -2
- package/ui/select/Select.js +42 -18
- package/ui/text/Text.d.ts +1 -0
- package/ui/text/Text.js +35 -30
- package/ui/theme/theme.d.ts +26 -2
- package/ui/theme/theme.js +253 -28
- package/utils/componentUtils.d.ts +48 -0
- package/utils/componentUtils.js +114 -0
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.6.
|
|
2
|
+
"version": "3.6.8",
|
|
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",
|
package/ui/button/Button.d.ts
CHANGED
|
@@ -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?: (
|
|
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 {};
|
package/ui/button/Button.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"".concat(
|
|
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 (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
}
|
package/ui/input/Input.d.ts
CHANGED
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 },
|
|
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 },
|
|
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 },
|
|
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
|
|
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 },
|
|
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" },
|
|
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
|
-
//
|
|
199
|
-
var
|
|
200
|
-
|
|
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
|
}
|
package/ui/select/Select.d.ts
CHANGED
|
@@ -10,8 +10,13 @@ interface CustomSelectProps {
|
|
|
10
10
|
defaultValue?: string;
|
|
11
11
|
placeholder?: string;
|
|
12
12
|
options: SelectOption[];
|
|
13
|
-
onChange?: (value: string,
|
|
14
|
-
|
|
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;
|
package/ui/select/Select.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
101
|
+
setInternalValue(option.value);
|
|
109
102
|
closeDropdown();
|
|
110
|
-
|
|
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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
'use client';
|
|
2
3
|
var __assign = (this && this.__assign) || function () {
|
|
3
4
|
__assign = Object.assign || function(t) {
|
|
4
5
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
@@ -28,52 +29,56 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
28
29
|
var react_1 = __importDefault(require("react"));
|
|
29
30
|
var pi_1 = require("react-icons/pi");
|
|
30
31
|
var getCssVariable_1 = require("../../utils/getCssVariable");
|
|
32
|
+
var componentUtils_1 = require("../../utils/componentUtils");
|
|
31
33
|
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 =
|
|
33
|
-
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
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"]);
|
|
35
|
+
// Use the component config hook
|
|
36
|
+
var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Text', variant).mergeWithLocal;
|
|
37
|
+
// Merge config with local props - local props override config
|
|
38
|
+
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;
|
|
39
|
+
var Tag = mergedProps.block ? 'div' : 'span';
|
|
40
|
+
var sizeClass = "".concat(mergedProps.size === 'h1' ? "h1" :
|
|
41
|
+
mergedProps.size === 'h2' ? "h2" :
|
|
42
|
+
mergedProps.size === 'h3' ? "h3" :
|
|
43
|
+
mergedProps.size === 'h4' ? "h4" :
|
|
44
|
+
mergedProps.size === 'h5' ? "h5" :
|
|
45
|
+
mergedProps.size === 'h6' ? "h6" :
|
|
46
|
+
"text-".concat(mergedProps.size));
|
|
42
47
|
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:
|
|
48
|
+
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
49
|
? {
|
|
45
50
|
display: '-webkit-box',
|
|
46
51
|
WebkitBoxOrient: 'vertical',
|
|
47
|
-
WebkitLineClamp: truncate,
|
|
52
|
+
WebkitLineClamp: mergedProps.truncate,
|
|
48
53
|
overflow: 'hidden',
|
|
49
54
|
textOverflow: 'ellipsis',
|
|
50
55
|
}
|
|
51
56
|
: {}));
|
|
52
57
|
var classNames = [
|
|
53
|
-
funcss || '',
|
|
58
|
+
mergedProps.funcss || '',
|
|
54
59
|
sizeClass,
|
|
55
|
-
color ? " text-".concat(color, " ") : '',
|
|
56
|
-
align ? " text-".concat(align, " ") : '',
|
|
57
|
-
monospace ? 'monospace' : '',
|
|
58
|
-
bg || '',
|
|
60
|
+
mergedProps.color ? " text-".concat(mergedProps.color, " ") : '',
|
|
61
|
+
mergedProps.align ? " text-".concat(mergedProps.align, " ") : '',
|
|
62
|
+
mergedProps.monospace ? 'monospace' : '',
|
|
63
|
+
mergedProps.bg || '',
|
|
59
64
|
hoverText ? "hover-text-".concat(hoverText) : '',
|
|
60
65
|
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 : '',
|
|
66
|
+
mergedProps.light ? 'lightText' : mergedProps.lighter ? 'lighterText' : '',
|
|
67
|
+
mergedProps.italic ? 'italicText' : '',
|
|
68
|
+
mergedProps.underline ? 'underlineText' : '',
|
|
69
|
+
mergedProps.body ? 'body' : '',
|
|
70
|
+
mergedProps.article ? 'article' : '',
|
|
71
|
+
mergedProps.emp ? 'emp' : '',
|
|
72
|
+
mergedProps.bold ? 'bold' : '',
|
|
73
|
+
mergedProps.uppercase ? 'uppercase' : '',
|
|
74
|
+
mergedProps.lowercase ? 'lowercase' : '',
|
|
75
|
+
mergedProps.capitalize ? 'capitalize' : '',
|
|
76
|
+
mergedProps.opacity ? 'opacity-' + mergedProps.opacity : '',
|
|
72
77
|
]
|
|
73
78
|
.filter(Boolean)
|
|
74
79
|
.join(' ');
|
|
75
|
-
return (react_1.default.createElement(Tag, __assign({ id: id, className: classNames, style: mergedStyles },
|
|
76
|
-
quote && (react_1.default.createElement("div", null,
|
|
80
|
+
return (react_1.default.createElement(Tag, __assign({ id: id, className: classNames, style: mergedStyles }, mergedProps),
|
|
81
|
+
mergedProps.quote && (react_1.default.createElement("div", null,
|
|
77
82
|
react_1.default.createElement(pi_1.PiQuotesLight, null))),
|
|
78
83
|
children,
|
|
79
84
|
text));
|
package/ui/theme/theme.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
82
|
+
var ThemeContext = (0, react_1.createContext)({
|
|
47
83
|
variant: 'standard',
|
|
48
|
-
setVariant: function () {
|
|
49
|
-
|
|
50
|
-
|
|
84
|
+
setVariant: function () { },
|
|
85
|
+
themeConfig: {},
|
|
86
|
+
projectData: null,
|
|
87
|
+
isLoading: true,
|
|
88
|
+
isInitialLoad: true,
|
|
89
|
+
error: null,
|
|
51
90
|
});
|
|
52
|
-
var
|
|
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)(
|
|
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
|
-
/* ----------------------
|
|
221
|
+
/* ---------------------- Firebase Theme Sync ----------------------- */
|
|
83
222
|
(0, react_1.useEffect)(function () {
|
|
84
223
|
if (typeof window === 'undefined' || !projectId) {
|
|
85
|
-
|
|
224
|
+
setIsLoading(false);
|
|
225
|
+
setIsInitialLoad(false);
|
|
86
226
|
return;
|
|
87
227
|
}
|
|
88
228
|
var root = document.documentElement;
|
|
89
|
-
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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;
|