@windrun-huaiin/third-ui 14.4.3 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fuma/mdx/gradient-button.d.ts +5 -1
- package/dist/fuma/mdx/gradient-button.js +10 -4
- package/dist/fuma/mdx/gradient-button.mjs +14 -8
- package/dist/main/index.d.ts +2 -0
- package/dist/main/index.js +10 -0
- package/dist/main/index.mjs +5 -0
- package/dist/main/pill-select/index.d.ts +4 -0
- package/dist/main/pill-select/index.js +13 -0
- package/dist/main/pill-select/index.mjs +4 -0
- package/dist/main/pill-select/x-filter-pills.d.ts +11 -0
- package/dist/main/pill-select/x-filter-pills.js +12 -0
- package/dist/main/pill-select/x-filter-pills.mjs +10 -0
- package/dist/main/pill-select/x-form-pills.d.ts +12 -0
- package/dist/main/pill-select/x-form-pills.js +12 -0
- package/dist/main/pill-select/x-form-pills.mjs +10 -0
- package/dist/main/pill-select/x-pill-select.d.ts +33 -0
- package/dist/main/pill-select/x-pill-select.js +142 -0
- package/dist/main/pill-select/x-pill-select.mjs +140 -0
- package/dist/main/pill-select/x-token-input.d.ts +12 -0
- package/dist/main/pill-select/x-token-input.js +71 -0
- package/dist/main/pill-select/x-token-input.mjs +69 -0
- package/dist/main/rich-text-expert.mjs +2 -2
- package/dist/main/x-button.d.ts +3 -0
- package/dist/main/x-button.js +29 -8
- package/dist/main/x-button.mjs +32 -11
- package/dist/main/x-toggle-button.d.ts +32 -0
- package/dist/main/x-toggle-button.js +95 -0
- package/dist/main/x-toggle-button.mjs +74 -0
- package/dist/node_modules/.pnpm/react-medium-image-zoom@5.4.1_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-medium-image-zoom/dist/Controlled.mjs +21 -21
- package/dist/node_modules/.pnpm/react-medium-image-zoom@5.4.1_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-medium-image-zoom/dist/Uncontrolled.mjs +4 -4
- package/dist/node_modules/.pnpm/react-medium-image-zoom@5.4.1_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-medium-image-zoom/dist/icons.mjs +5 -5
- package/dist/node_modules/.pnpm/swiper@12.1.3/node_modules/swiper/swiper-react.mjs +18 -18
- package/package.json +8 -8
- package/src/fuma/mdx/gradient-button.tsx +40 -4
- package/src/main/index.ts +2 -0
- package/src/main/pill-select/index.ts +4 -0
- package/src/main/pill-select/x-filter-pills.tsx +36 -0
- package/src/main/pill-select/x-form-pills.tsx +39 -0
- package/src/main/pill-select/x-pill-select.tsx +360 -0
- package/src/main/pill-select/x-token-input.tsx +174 -0
- package/src/main/x-button.tsx +64 -8
- package/src/main/x-toggle-button.tsx +218 -0
- package/src/clerk/patch/optional-auth.ts +0 -24
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React__default from 'react';
|
|
2
2
|
import ReactDOM from 'react-dom';
|
|
3
3
|
import { IEnlarge, ICompress } from './icons.mjs';
|
|
4
4
|
import { getStyleGhost, getImgSrc, testImg, testImgLoaded, testSvg, adjustSvgIDs, testDiv, getImgAlt, getStyleModalImg } from './utils.mjs';
|
|
@@ -11,9 +11,9 @@ const defaultBodyAttrs = {
|
|
|
11
11
|
width: '',
|
|
12
12
|
};
|
|
13
13
|
function Controlled(props) {
|
|
14
|
-
return
|
|
14
|
+
return React__default.createElement(ControlledBase, { ...props });
|
|
15
15
|
}
|
|
16
|
-
class ControlledBase extends
|
|
16
|
+
class ControlledBase extends React__default.Component {
|
|
17
17
|
constructor() {
|
|
18
18
|
super(...arguments);
|
|
19
19
|
this.state = {
|
|
@@ -24,11 +24,11 @@ class ControlledBase extends React.Component {
|
|
|
24
24
|
shouldRefresh: false,
|
|
25
25
|
styleGhost: {},
|
|
26
26
|
};
|
|
27
|
-
this.refContent =
|
|
28
|
-
this.refDialog =
|
|
29
|
-
this.refModalContent =
|
|
30
|
-
this.refModalImg =
|
|
31
|
-
this.refWrap =
|
|
27
|
+
this.refContent = React__default.createRef();
|
|
28
|
+
this.refDialog = React__default.createRef();
|
|
29
|
+
this.refModalContent = React__default.createRef();
|
|
30
|
+
this.refModalImg = React__default.createRef();
|
|
31
|
+
this.refWrap = React__default.createRef();
|
|
32
32
|
this.imgEl = null;
|
|
33
33
|
this.isScaling = false;
|
|
34
34
|
this.prevBodyAttrs = defaultBodyAttrs;
|
|
@@ -371,24 +371,24 @@ class ControlledBase extends React.Component {
|
|
|
371
371
|
: {};
|
|
372
372
|
let modalContent = null;
|
|
373
373
|
if (hasImage) {
|
|
374
|
-
const modalImg = isImg || isDiv ? (
|
|
374
|
+
const modalImg = isImg || isDiv ? (React__default.createElement("img", { alt: imgAlt, crossOrigin: imgCrossOrigin, sizes: imgSizes, src: imgSrc, srcSet: imgSrcSet, ...(isZoomImgLoaded && modalState === "LOADED"
|
|
375
375
|
? zoomImg
|
|
376
|
-
: {}), "data-rmiz-modal-img": "", height: this.styleModalImg.height || undefined, id: idModalImg, ref: refModalImg, style: this.styleModalImg, width: this.styleModalImg.width || undefined })) : isSvg ? (
|
|
377
|
-
const modalBtnUnzoom = (
|
|
378
|
-
|
|
379
|
-
modalContent = ZoomContent ? (
|
|
376
|
+
: {}), "data-rmiz-modal-img": "", height: this.styleModalImg.height || undefined, id: idModalImg, ref: refModalImg, style: this.styleModalImg, width: this.styleModalImg.width || undefined })) : isSvg ? (React__default.createElement("div", { "data-rmiz-modal-img": true, ref: refModalImg, style: this.styleModalImg })) : null;
|
|
377
|
+
const modalBtnUnzoom = (React__default.createElement("button", { "aria-label": a11yNameButtonUnzoom, "data-rmiz-btn-unzoom": "", onClick: handleBtnUnzoomClick, type: "button" },
|
|
378
|
+
React__default.createElement(IconUnzoom, null)));
|
|
379
|
+
modalContent = ZoomContent ? (React__default.createElement(ZoomContent, { buttonUnzoom: modalBtnUnzoom, modalState: modalState, img: modalImg, isZoomImgLoaded: isZoomImgLoaded, onUnzoom: handleUnzoom })) : (React__default.createElement(React__default.Fragment, null,
|
|
380
380
|
modalImg,
|
|
381
381
|
modalBtnUnzoom));
|
|
382
382
|
}
|
|
383
|
-
return (
|
|
384
|
-
|
|
385
|
-
hasImage && (
|
|
386
|
-
|
|
387
|
-
|
|
383
|
+
return (React__default.createElement(WrapElement, { "aria-owns": idModal, "data-rmiz": "", ref: refWrap },
|
|
384
|
+
React__default.createElement(WrapElement, { "data-rmiz-content": dataContentState, ref: refContent, style: styleContent }, children),
|
|
385
|
+
hasImage && (React__default.createElement(WrapElement, { "data-rmiz-ghost": "", style: styleGhost },
|
|
386
|
+
React__default.createElement("button", { "aria-label": labelBtnZoom, "data-rmiz-btn-zoom": "", onClick: handleZoom, type: "button" },
|
|
387
|
+
React__default.createElement(IconZoom, null)))),
|
|
388
388
|
hasImage &&
|
|
389
|
-
ReactDOM.createPortal(
|
|
390
|
-
|
|
391
|
-
|
|
389
|
+
ReactDOM.createPortal(React__default.createElement("dialog", { "aria-labelledby": idModalImg, "aria-modal": "true", className: classDialog, "data-rmiz-modal": "", id: idModal, onClick: handleDialogClick, onClose: handleDialogClose, onCancel: handleDialogCancel, ref: refDialog, role: "dialog" },
|
|
390
|
+
React__default.createElement("div", { "data-rmiz-modal-overlay": dataOverlayState }),
|
|
391
|
+
React__default.createElement("div", { "data-rmiz-modal-content": "", ref: refModalContent }, modalContent)), this.getDialogContainer())));
|
|
392
392
|
}
|
|
393
393
|
componentDidMount() {
|
|
394
394
|
this.setId();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React__default from 'react';
|
|
2
2
|
import { Controlled } from './Controlled.mjs';
|
|
3
3
|
|
|
4
4
|
function Uncontrolled({ onZoomChange, ...props }) {
|
|
5
|
-
const [isZoomed, setIsZoomed] =
|
|
6
|
-
const handleZoomChange =
|
|
5
|
+
const [isZoomed, setIsZoomed] = React__default.useState(false);
|
|
6
|
+
const handleZoomChange = React__default.useCallback((value, { event }) => {
|
|
7
7
|
setIsZoomed(value);
|
|
8
8
|
onZoomChange?.(value, { event });
|
|
9
9
|
}, [onZoomChange]);
|
|
10
|
-
return (
|
|
10
|
+
return (React__default.createElement(Controlled, { ...props, isZoomed: isZoomed, onZoomChange: handleZoomChange }));
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export { Uncontrolled };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React__default from 'react';
|
|
2
2
|
|
|
3
3
|
function ICompress() {
|
|
4
|
-
return (
|
|
5
|
-
|
|
4
|
+
return (React__default.createElement("svg", { "aria-hidden": "true", "data-rmiz-btn-unzoom-icon": true, fill: "currentColor", focusable: "false", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg" },
|
|
5
|
+
React__default.createElement("path", { d: "M 14.144531 1.148438 L 9 6.292969 L 9 3 L 8 3 L 8 8 L 13 8 L 13 7 L 9.707031 7 L 14.855469 1.851563 Z M 8 8 L 3 8 L 3 9 L 6.292969 9 L 1.148438 14.144531 L 1.851563 14.855469 L 7 9.707031 L 7 13 L 8 13 Z" })));
|
|
6
6
|
}
|
|
7
7
|
function IEnlarge() {
|
|
8
|
-
return (
|
|
9
|
-
|
|
8
|
+
return (React__default.createElement("svg", { "aria-hidden": "true", "data-rmiz-btn-zoom-icon": true, fill: "currentColor", focusable: "false", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg" },
|
|
9
|
+
React__default.createElement("path", { d: "M 9 1 L 9 2 L 12.292969 2 L 2 12.292969 L 2 9 L 1 9 L 1 14 L 6 14 L 6 13 L 2.707031 13 L 13 2.707031 L 13 6 L 14 6 L 14 1 Z" })));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export { ICompress, IEnlarge };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React__default, { forwardRef, useState, useRef, useEffect, createContext, useLayoutEffect } from 'react';
|
|
2
2
|
import { S as Swiper$1 } from './shared/swiper-core.mjs';
|
|
3
3
|
import { g as getParams, m as mountSwiper, a as getChangedParams, u as updateOnVirtualData } from './shared/update-on-virtual-data.mjs';
|
|
4
4
|
import { d as uniqueClasses, w as wrapperClass, n as needsNavigation, b as needsScrollbar, a as needsPagination, e as extend, u as updateSwiper } from './shared/update-swiper.mjs';
|
|
@@ -36,7 +36,7 @@ function isChildSwiperSlide(child) {
|
|
|
36
36
|
}
|
|
37
37
|
function processChildren(c) {
|
|
38
38
|
const slides = [];
|
|
39
|
-
|
|
39
|
+
React__default.Children.toArray(c).forEach(child => {
|
|
40
40
|
if (isChildSwiperSlide(child)) {
|
|
41
41
|
slides.push(child);
|
|
42
42
|
} else if (child.props && child.props.children) {
|
|
@@ -53,7 +53,7 @@ function getChildren(c) {
|
|
|
53
53
|
'wrapper-start': [],
|
|
54
54
|
'wrapper-end': []
|
|
55
55
|
};
|
|
56
|
-
|
|
56
|
+
React__default.Children.toArray(c).forEach(child => {
|
|
57
57
|
if (isChildSwiperSlide(child)) {
|
|
58
58
|
slides.push(child);
|
|
59
59
|
} else if (child.props && child.props.slot && slots[child.props.slot]) {
|
|
@@ -105,7 +105,7 @@ function renderVirtual(swiper, slides, virtualData) {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
return slidesToRender.map((child, index) => {
|
|
108
|
-
return /*#__PURE__*/
|
|
108
|
+
return /*#__PURE__*/React__default.cloneElement(child, {
|
|
109
109
|
swiper,
|
|
110
110
|
style,
|
|
111
111
|
key: child.props.virtualIndex || child.key || `slide-${index}`
|
|
@@ -276,29 +276,29 @@ const Swiper = /*#__PURE__*/forwardRef(({
|
|
|
276
276
|
return renderVirtual(swiperRef.current, slides, virtualData);
|
|
277
277
|
}
|
|
278
278
|
return slides.map((child, index) => {
|
|
279
|
-
return /*#__PURE__*/
|
|
279
|
+
return /*#__PURE__*/React__default.cloneElement(child, {
|
|
280
280
|
swiper: swiperRef.current,
|
|
281
281
|
swiperSlideIndex: index
|
|
282
282
|
});
|
|
283
283
|
});
|
|
284
284
|
}
|
|
285
|
-
return /*#__PURE__*/
|
|
285
|
+
return /*#__PURE__*/React__default.createElement(Tag, _extends({
|
|
286
286
|
ref: swiperElRef,
|
|
287
287
|
className: uniqueClasses(`${containerClasses}${className ? ` ${className}` : ''}`)
|
|
288
|
-
}, restProps), /*#__PURE__*/
|
|
288
|
+
}, restProps), /*#__PURE__*/React__default.createElement(SwiperContext.Provider, {
|
|
289
289
|
value: swiperRef.current
|
|
290
|
-
}, slots['container-start'], /*#__PURE__*/
|
|
290
|
+
}, slots['container-start'], /*#__PURE__*/React__default.createElement(WrapperTag, {
|
|
291
291
|
className: wrapperClass(swiperParams.wrapperClass)
|
|
292
|
-
}, slots['wrapper-start'], renderSlides(), slots['wrapper-end']), needsNavigation(swiperParams) && /*#__PURE__*/
|
|
292
|
+
}, slots['wrapper-start'], renderSlides(), slots['wrapper-end']), needsNavigation(swiperParams) && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("div", {
|
|
293
293
|
ref: prevElRef,
|
|
294
294
|
className: "swiper-button-prev"
|
|
295
|
-
}), /*#__PURE__*/
|
|
295
|
+
}), /*#__PURE__*/React__default.createElement("div", {
|
|
296
296
|
ref: nextElRef,
|
|
297
297
|
className: "swiper-button-next"
|
|
298
|
-
})), needsScrollbar(swiperParams) && /*#__PURE__*/
|
|
298
|
+
})), needsScrollbar(swiperParams) && /*#__PURE__*/React__default.createElement("div", {
|
|
299
299
|
ref: scrollbarElRef,
|
|
300
300
|
className: "swiper-scrollbar"
|
|
301
|
-
}), needsPagination(swiperParams) && /*#__PURE__*/
|
|
301
|
+
}), needsPagination(swiperParams) && /*#__PURE__*/React__default.createElement("div", {
|
|
302
302
|
ref: paginationElRef,
|
|
303
303
|
className: "swiper-pagination"
|
|
304
304
|
}), slots['container-end']));
|
|
@@ -364,24 +364,24 @@ const SwiperSlide = /*#__PURE__*/forwardRef(({
|
|
|
364
364
|
const onLoad = () => {
|
|
365
365
|
setLazyLoaded(true);
|
|
366
366
|
};
|
|
367
|
-
return /*#__PURE__*/
|
|
367
|
+
return /*#__PURE__*/React__default.createElement(Tag, _extends({
|
|
368
368
|
ref: slideElRef,
|
|
369
369
|
className: uniqueClasses(`${slideClasses}${className ? ` ${className}` : ''}`),
|
|
370
370
|
"data-swiper-slide-index": virtualIndex,
|
|
371
371
|
onLoad: onLoad
|
|
372
|
-
}, rest), zoom && /*#__PURE__*/
|
|
372
|
+
}, rest), zoom && /*#__PURE__*/React__default.createElement(SwiperSlideContext.Provider, {
|
|
373
373
|
value: slideData
|
|
374
|
-
}, /*#__PURE__*/
|
|
374
|
+
}, /*#__PURE__*/React__default.createElement("div", {
|
|
375
375
|
className: "swiper-zoom-container",
|
|
376
376
|
"data-swiper-zoom": typeof zoom === 'number' ? zoom : undefined
|
|
377
|
-
}, renderChildren(), lazy && !lazyLoaded && /*#__PURE__*/
|
|
377
|
+
}, renderChildren(), lazy && !lazyLoaded && /*#__PURE__*/React__default.createElement("div", {
|
|
378
378
|
className: "swiper-lazy-preloader",
|
|
379
379
|
ref: node => {
|
|
380
380
|
if (node) node.lazyPreloaderManaged = true;
|
|
381
381
|
}
|
|
382
|
-
}))), !zoom && /*#__PURE__*/
|
|
382
|
+
}))), !zoom && /*#__PURE__*/React__default.createElement(SwiperSlideContext.Provider, {
|
|
383
383
|
value: slideData
|
|
384
|
-
}, renderChildren(), lazy && !lazyLoaded && /*#__PURE__*/
|
|
384
|
+
}, renderChildren(), lazy && !lazyLoaded && /*#__PURE__*/React__default.createElement("div", {
|
|
385
385
|
className: "swiper-lazy-preloader",
|
|
386
386
|
ref: node => {
|
|
387
387
|
if (node) node.lazyPreloaderManaged = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windrun-huaiin/third-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "Third-party integrated UI components for windrun-huaiin projects",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -16,11 +16,6 @@
|
|
|
16
16
|
"import": "./dist/clerk/server.mjs",
|
|
17
17
|
"require": "./dist/clerk/server.js"
|
|
18
18
|
},
|
|
19
|
-
"./clerk/patch/optional-auth": {
|
|
20
|
-
"types": "./dist/clerk/patch/optional-auth.d.ts",
|
|
21
|
-
"import": "./dist/clerk/patch/optional-auth.mjs",
|
|
22
|
-
"require": "./dist/clerk/patch/optional-auth.js"
|
|
23
|
-
},
|
|
24
19
|
"./fingerprint": {
|
|
25
20
|
"types": "./dist/clerk/fingerprint/index.d.ts",
|
|
26
21
|
"import": "./dist/clerk/fingerprint/index.mjs",
|
|
@@ -36,6 +31,11 @@
|
|
|
36
31
|
"import": "./dist/main/index.mjs",
|
|
37
32
|
"require": "./dist/main/index.js"
|
|
38
33
|
},
|
|
34
|
+
"./main/pill-select": {
|
|
35
|
+
"types": "./dist/main/pill-select/index.d.ts",
|
|
36
|
+
"import": "./dist/main/pill-select/index.mjs",
|
|
37
|
+
"require": "./dist/main/pill-select/index.js"
|
|
38
|
+
},
|
|
39
39
|
"./main/server": {
|
|
40
40
|
"types": "./dist/main/server.d.ts",
|
|
41
41
|
"import": "./dist/main/server.mjs",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"react-medium-image-zoom": "^5.4.1",
|
|
88
88
|
"swiper": "^12.1.2",
|
|
89
89
|
"zod": "^4.3.6",
|
|
90
|
-
"@windrun-huaiin/
|
|
91
|
-
"@windrun-huaiin/
|
|
90
|
+
"@windrun-huaiin/lib": "^15.0.0",
|
|
91
|
+
"@windrun-huaiin/base-ui": "^15.0.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependencies": {
|
|
94
94
|
"clsx": "^2.1.1",
|
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import { cn } from '@windrun-huaiin/lib/utils';
|
|
4
4
|
import { globalLucideIcons as icons } from "@windrun-huaiin/base-ui/components/server";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
themeBgColor,
|
|
7
|
+
themeBorderColor,
|
|
8
|
+
themeButtonGradientClass,
|
|
9
|
+
themeButtonGradientHoverClass,
|
|
10
|
+
themeIconColor,
|
|
11
|
+
themeMainBgColor,
|
|
12
|
+
} from "@windrun-huaiin/base-ui/lib";
|
|
6
13
|
import Link from "next/link";
|
|
7
14
|
import React, { useState } from 'react';
|
|
8
15
|
|
|
16
|
+
type GradientButtonVariant = 'default' | 'soft' | 'subtle';
|
|
17
|
+
|
|
9
18
|
export interface GradientButtonProps {
|
|
10
19
|
title: React.ReactNode;
|
|
11
20
|
icon?: React.ReactNode;
|
|
21
|
+
iconForcePosition?: 'left' | 'right';
|
|
12
22
|
align?: 'left' | 'center' | 'right';
|
|
13
23
|
disabled?: boolean;
|
|
14
24
|
className?: string;
|
|
@@ -22,11 +32,13 @@ export interface GradientButtonProps {
|
|
|
22
32
|
onClick?: () => void | Promise<void>;
|
|
23
33
|
loadingText?: React.ReactNode;
|
|
24
34
|
preventDoubleClick?: boolean;
|
|
35
|
+
variant?: GradientButtonVariant;
|
|
25
36
|
}
|
|
26
37
|
|
|
27
38
|
export function GradientButton({
|
|
28
39
|
title,
|
|
29
40
|
icon,
|
|
41
|
+
iconForcePosition,
|
|
30
42
|
align = 'left',
|
|
31
43
|
disabled = false,
|
|
32
44
|
className = "",
|
|
@@ -37,12 +49,16 @@ export function GradientButton({
|
|
|
37
49
|
loadingText,
|
|
38
50
|
preventDoubleClick = true,
|
|
39
51
|
iconClassName,
|
|
52
|
+
variant = 'default',
|
|
40
53
|
}: GradientButtonProps) {
|
|
41
54
|
const [isLoading, setIsLoading] = useState(false);
|
|
42
55
|
const actualLoadingText = loadingText || title?.toString().trim() || 'Loading...'
|
|
43
56
|
|
|
44
57
|
const defaultIconClass = "h-4 w-4";
|
|
45
|
-
const finalIconClass = cn(
|
|
58
|
+
const finalIconClass = cn(
|
|
59
|
+
variant === 'default' ? 'text-white' : themeIconColor,
|
|
60
|
+
iconClassName || defaultIconClass
|
|
61
|
+
);
|
|
46
62
|
|
|
47
63
|
// set justify class according to alignment
|
|
48
64
|
const getAlignmentClass = () => {
|
|
@@ -111,8 +127,9 @@ export function GradientButton({
|
|
|
111
127
|
})();
|
|
112
128
|
|
|
113
129
|
const shouldRenderIcon = iconNode !== null && iconNode !== undefined;
|
|
130
|
+
const iconPosition = iconForcePosition ?? (onClick ? 'left' : 'right');
|
|
114
131
|
|
|
115
|
-
const buttonContent =
|
|
132
|
+
const buttonContent = iconPosition === 'left' ? (
|
|
116
133
|
<>
|
|
117
134
|
{shouldRenderIcon ? <span>{iconNode}</span> : null}
|
|
118
135
|
<span className={cn(shouldRenderIcon && 'ml-1')}>{displayTitle}</span>
|
|
@@ -133,10 +150,29 @@ export function GradientButton({
|
|
|
133
150
|
// Base styles extracted from Button component + size="lg" (h-11 px-8)
|
|
134
151
|
// Removed [&_svg] constraints
|
|
135
152
|
const baseButtonStyles = "inline-flex items-center gap-2 whitespace-nowrap h-11 px-8 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50";
|
|
153
|
+
const variantClassName = variant === 'soft'
|
|
154
|
+
? cn(
|
|
155
|
+
themeBgColor,
|
|
156
|
+
themeIconColor,
|
|
157
|
+
themeBorderColor,
|
|
158
|
+
'border shadow-sm hover:shadow-md hover:brightness-95'
|
|
159
|
+
)
|
|
160
|
+
: variant === 'subtle'
|
|
161
|
+
? cn(
|
|
162
|
+
themeMainBgColor,
|
|
163
|
+
themeIconColor,
|
|
164
|
+
'border border-neutral-200 shadow-sm hover:shadow-md hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-800'
|
|
165
|
+
)
|
|
166
|
+
: cn(
|
|
167
|
+
themeButtonGradientClass,
|
|
168
|
+
themeButtonGradientHoverClass,
|
|
169
|
+
'text-white shadow-lg hover:shadow-xl'
|
|
170
|
+
);
|
|
136
171
|
|
|
137
172
|
const buttonClassName = cn(
|
|
138
173
|
baseButtonStyles,
|
|
139
|
-
|
|
174
|
+
variantClassName,
|
|
175
|
+
'text-base font-bold transition-all duration-300 rounded-full',
|
|
140
176
|
alignmentClass,
|
|
141
177
|
isDisabled && 'opacity-50 cursor-not-allowed',
|
|
142
178
|
className,
|
package/src/main/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './loading';
|
|
|
6
6
|
export * from './nprogress-bar';
|
|
7
7
|
export * from './ads-alert-dialog';
|
|
8
8
|
export * from './x-button'
|
|
9
|
+
export * from './x-toggle-button'
|
|
9
10
|
export * from './ai-prompt-textarea'
|
|
10
11
|
export * from './rich-text-expert'
|
|
11
12
|
export * from './faq-interactive'
|
|
@@ -13,6 +14,7 @@ export * from './price-plan-interactive'
|
|
|
13
14
|
export * from './gallery/gallery-interactive'
|
|
14
15
|
export * from './delayed-img'
|
|
15
16
|
export * from './snake-loading-frame'
|
|
17
|
+
export * from './pill-select'
|
|
16
18
|
// Money Price Client Components
|
|
17
19
|
export { MoneyPriceInteractive } from './money-price/money-price-interactive';
|
|
18
20
|
export { MoneyPriceButton } from './money-price/money-price-button';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@windrun-huaiin/lib/utils';
|
|
4
|
+
import { XPillSelect, type XPillOption } from './x-pill-select';
|
|
5
|
+
|
|
6
|
+
type XFilterPillsProps = {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
options: XPillOption[];
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
allLabel: string;
|
|
12
|
+
className?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function XFilterPills({
|
|
16
|
+
label,
|
|
17
|
+
value,
|
|
18
|
+
options,
|
|
19
|
+
onChange,
|
|
20
|
+
allLabel,
|
|
21
|
+
className,
|
|
22
|
+
}: XFilterPillsProps) {
|
|
23
|
+
return (
|
|
24
|
+
<div className={cn('space-y-1.5', className)}>
|
|
25
|
+
<div className="text-xs font-medium text-slate-700 dark:text-slate-200">{label}</div>
|
|
26
|
+
<XPillSelect
|
|
27
|
+
mode="single"
|
|
28
|
+
value={value}
|
|
29
|
+
onChange={onChange}
|
|
30
|
+
options={[{ label: allLabel, value: '' }, ...options]}
|
|
31
|
+
size="compact"
|
|
32
|
+
maxPillWidthClassName="max-w-[150px] sm:max-w-[220px]"
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@windrun-huaiin/lib/utils';
|
|
4
|
+
import { XPillSelect, type XPillOption } from './x-pill-select';
|
|
5
|
+
|
|
6
|
+
type XFormPillsProps = {
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
value: string;
|
|
9
|
+
options: XPillOption[];
|
|
10
|
+
onChange: (value: string) => void;
|
|
11
|
+
emptyLabel: string;
|
|
12
|
+
allowClear?: boolean;
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function XFormPills({
|
|
17
|
+
label,
|
|
18
|
+
value,
|
|
19
|
+
options,
|
|
20
|
+
onChange,
|
|
21
|
+
emptyLabel,
|
|
22
|
+
allowClear = false,
|
|
23
|
+
className,
|
|
24
|
+
}: XFormPillsProps) {
|
|
25
|
+
return (
|
|
26
|
+
<div className={cn('space-y-2 text-sm', className)}>
|
|
27
|
+
<div className="font-medium text-slate-700 dark:text-slate-200">{label}</div>
|
|
28
|
+
<XPillSelect
|
|
29
|
+
mode="single"
|
|
30
|
+
value={value}
|
|
31
|
+
onChange={onChange}
|
|
32
|
+
options={options}
|
|
33
|
+
emptyLabel={emptyLabel}
|
|
34
|
+
allowClear={allowClear}
|
|
35
|
+
maxPillWidthClassName="max-w-[150px] sm:max-w-[220px]"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
}
|