lupine.components 1.1.21 → 1.1.23
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/src/components/action-sheet-demo.tsx +105 -0
- package/src/components/button-demo.tsx +33 -0
- package/src/components/button-push-animation-demo.tsx +32 -0
- package/src/components/button-push-animation.tsx +8 -4
- package/src/components/editable-label-demo.tsx +33 -0
- package/src/components/input-with-title-demo.tsx +42 -0
- package/src/components/message-box-demo.tsx +107 -0
- package/src/components/modal-demo.tsx +56 -0
- package/src/components/notice-message-demo.tsx +60 -0
- package/src/components/popup-menu-demo.tsx +68 -0
- package/src/components/popup-menu.tsx +1 -1
- package/src/components/progress-demo.tsx +63 -0
- package/src/components/progress.tsx +3 -3
- package/src/components/radio-label-demo.tsx +41 -0
- package/src/components/redirect-demo.tsx +36 -0
- package/src/components/resizable-splitter-demo.tsx +76 -0
- package/src/components/resizable-splitter.tsx +6 -6
- package/src/components/select-angle-demo.tsx +32 -0
- package/src/components/select-with-title-demo.tsx +53 -0
- package/src/components/spinner-demo.tsx +52 -0
- package/src/components/stars-component-demo.tsx +36 -0
- package/src/components/stars-component.tsx +11 -3
- package/src/components/switch-option-demo.tsx +36 -0
- package/src/components/tabs-demo.tsx +42 -0
- package/src/components/text-glow-demo.tsx +46 -0
- package/src/components/text-scale-demo.tsx +41 -0
- package/src/components/text-wave-demo.tsx +46 -0
- package/src/components/toggle-button-demo.tsx +42 -0
- package/src/components/toggle-play-button-demo.tsx +56 -0
- package/src/components/toggle-switch-demo.tsx +43 -0
- package/src/demo/demo-about.tsx +12 -0
- package/src/demo/demo-container.tsx +57 -0
- package/src/demo/demo-css.tsx +3 -0
- package/src/demo/demo-frame-helper.tsx +395 -0
- package/src/demo/demo-frame.tsx +139 -0
- package/src/demo/demo-index.tsx +17 -0
- package/src/demo/demo-page.tsx +198 -0
- package/src/demo/demo-registry.ts +54 -0
- package/src/demo/demo-render-page.tsx +77 -0
- package/src/demo/demo-types.ts +22 -0
- package/src/html-editor/buttons_morden.gif +0 -0
- package/src/html-editor/h-editor.ts +817 -0
- package/src/index.ts +2 -0
|
@@ -2,7 +2,7 @@ import { CssProps, RefProps } from 'lupine.web';
|
|
|
2
2
|
import { HtmlVar } from './html-var';
|
|
3
3
|
|
|
4
4
|
export type ProgressHookProps = {
|
|
5
|
-
onProgress?: (percentage: number, chunkNumber
|
|
5
|
+
onProgress?: (percentage: number, chunkNumber?: number, totalChunks?: number) => void;
|
|
6
6
|
onShow?: (show: boolean, title?: string) => void;
|
|
7
7
|
};
|
|
8
8
|
export type ProgressProps = {
|
|
@@ -53,13 +53,13 @@ export const Progress = (props: ProgressProps) => {
|
|
|
53
53
|
},
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
props.hook.onProgress = (percentage: number, chunkNumber
|
|
56
|
+
props.hook.onProgress = (percentage: number, chunkNumber?: number, totalChunks?: number) => {
|
|
57
57
|
// console.log(`Upload progress: ${percentage}% (chunk ${chunkNumber} of ${totalChunks})`);
|
|
58
58
|
percentage = Math.round(percentage * 100);
|
|
59
59
|
const bar1 = document.querySelector('.progress-bar1') as HTMLElement;
|
|
60
60
|
const bar2 = document.querySelector('.progress-bar2') as HTMLElement;
|
|
61
61
|
bar1.style.width = `${percentage}%`;
|
|
62
|
-
bar2.style.width = `${
|
|
62
|
+
bar2.style.width = `${100 - percentage}%`;
|
|
63
63
|
dom.value = `${percentage}%`;
|
|
64
64
|
};
|
|
65
65
|
props.hook.onShow = (show: boolean, title?: string) => {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { RadioLabelComponent } from './radio-label-component';
|
|
3
|
+
|
|
4
|
+
export const radioLabelDemo: DemoStory<any> = {
|
|
5
|
+
id: 'radio-label-demo',
|
|
6
|
+
text: 'Radio Label Demo',
|
|
7
|
+
args: {
|
|
8
|
+
label: 'Option A',
|
|
9
|
+
name: 'demo-radio-group',
|
|
10
|
+
checked: true,
|
|
11
|
+
disabled: false,
|
|
12
|
+
},
|
|
13
|
+
argTypes: {
|
|
14
|
+
label: { control: 'text', description: 'Label text' },
|
|
15
|
+
name: { control: 'text', description: 'Radio group name' },
|
|
16
|
+
checked: { control: 'boolean', description: 'Is checked?' },
|
|
17
|
+
disabled: { control: 'boolean', description: 'Is disabled?' },
|
|
18
|
+
},
|
|
19
|
+
render: (args) => {
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ padding: '20px', display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
|
22
|
+
<RadioLabelComponent {...args} />
|
|
23
|
+
<RadioLabelComponent label='Option B' name={args.name} disabled={args.disabled} />
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
},
|
|
27
|
+
code: `import { RadioLabelComponent } from 'lupine.components/components/radio-label-component';
|
|
28
|
+
|
|
29
|
+
<RadioLabelComponent
|
|
30
|
+
label="Option A"
|
|
31
|
+
name="demo-radio-group"
|
|
32
|
+
checked={true}
|
|
33
|
+
disabled={false}
|
|
34
|
+
/>
|
|
35
|
+
<RadioLabelComponent
|
|
36
|
+
label="Option B"
|
|
37
|
+
name="demo-radio-group"
|
|
38
|
+
disabled={false}
|
|
39
|
+
/>
|
|
40
|
+
`,
|
|
41
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { Redirect, RedirectProps } from './redirect';
|
|
3
|
+
|
|
4
|
+
export const redirectDemo: DemoStory<RedirectProps> = {
|
|
5
|
+
id: 'redirect-demo',
|
|
6
|
+
text: 'Redirect Demo',
|
|
7
|
+
args: {
|
|
8
|
+
title: 'Redirecting you soon...' + new Date().toISOString(),
|
|
9
|
+
url: '#test-redirect',
|
|
10
|
+
delaySeconds: 3,
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
title: { control: 'text', description: 'Text shown while waiting' },
|
|
14
|
+
url: { control: 'text', description: 'URL to redirect to' },
|
|
15
|
+
delaySeconds: { control: 'number', description: 'Delay before redirecting' },
|
|
16
|
+
},
|
|
17
|
+
render: (args) => {
|
|
18
|
+
return (
|
|
19
|
+
<div style={{ padding: '20px', border: '1px solid #ccc', backgroundColor: '#f9f9f9' }}>
|
|
20
|
+
<p style={{ color: '#666', marginBottom: '16px' }}>
|
|
21
|
+
This component automatically changes the `window.location.href` after the specified delay. In this demo, the
|
|
22
|
+
iframe will redirect itself to `{args.url}` after {args.delaySeconds} seconds.
|
|
23
|
+
</p>
|
|
24
|
+
<Redirect {...args} />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
code: `import { Redirect } from 'lupine.components/components/redirect';
|
|
29
|
+
|
|
30
|
+
<Redirect
|
|
31
|
+
title="Redirecting you soon..."
|
|
32
|
+
url="https://example.com"
|
|
33
|
+
delaySeconds={3}
|
|
34
|
+
/>
|
|
35
|
+
`,
|
|
36
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { ResizableSplitter } from './resizable-splitter';
|
|
3
|
+
|
|
4
|
+
export const resizableSplitterDemo: DemoStory<any> = {
|
|
5
|
+
id: 'resizable-splitter-demo',
|
|
6
|
+
text: 'Resizable Splitter Demo',
|
|
7
|
+
args: {
|
|
8
|
+
isVertical: true,
|
|
9
|
+
},
|
|
10
|
+
argTypes: {
|
|
11
|
+
isVertical: { control: 'boolean', description: 'If true, splits left/right. If false, splits top/bottom' },
|
|
12
|
+
},
|
|
13
|
+
render: (args) => {
|
|
14
|
+
// The splitter hook targets a selector, so we create a unique container.
|
|
15
|
+
const containerId = 'splitter-demo-box';
|
|
16
|
+
|
|
17
|
+
// The logic expects to re-mount the splitter or reload the page for structural updates normally,
|
|
18
|
+
// but we can hack it together for the demo by destroying and recreating the DOM.
|
|
19
|
+
// For simplicity, we just use a fixed layout that reacts to the boolean toggle.
|
|
20
|
+
|
|
21
|
+
if (args.isVertical) {
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ display: 'flex', width: '600px', height: '400px', border: '1px solid #999', padding: '20px' }}>
|
|
24
|
+
<div
|
|
25
|
+
id={containerId}
|
|
26
|
+
style={{
|
|
27
|
+
width: '200px',
|
|
28
|
+
height: '100%',
|
|
29
|
+
backgroundColor: '#eee',
|
|
30
|
+
position: 'relative',
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<div style={{ padding: '10px' }}>Left Panel (Drag right edge)</div>
|
|
34
|
+
{ResizableSplitter.getSplitter(`#${containerId}`, true, true)}
|
|
35
|
+
</div>
|
|
36
|
+
<div style={{ flex: 1, backgroundColor: '#ddd', padding: '10px' }}>Right Panel (Flex 1)</div>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
} else {
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
display: 'flex',
|
|
44
|
+
flexDirection: 'column',
|
|
45
|
+
width: '600px',
|
|
46
|
+
height: '400px',
|
|
47
|
+
border: '1px solid #999',
|
|
48
|
+
padding: '20px',
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<div
|
|
52
|
+
id={containerId}
|
|
53
|
+
style={{
|
|
54
|
+
height: '150px',
|
|
55
|
+
width: '100%',
|
|
56
|
+
backgroundColor: '#eee',
|
|
57
|
+
position: 'relative',
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<div style={{ padding: '10px' }}>Top Panel (Drag bottom edge)</div>
|
|
61
|
+
{ResizableSplitter.getSplitter(`#${containerId}`, false, false)}
|
|
62
|
+
</div>
|
|
63
|
+
<div style={{ flex: 1, backgroundColor: '#ddd', padding: '10px' }}>Bottom Panel (Flex 1)</div>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
code: `import { ResizableSplitter } from 'lupine.components/components/resizable-splitter';
|
|
69
|
+
|
|
70
|
+
{/* Left/Right Splitter (isVertical=true means the divider line is vertical) */}
|
|
71
|
+
<div id="splitter-demo-box" style={{ width: '200px', height: '100%', position: 'relative' }}>
|
|
72
|
+
<div style={{ padding: '10px' }}>Left Panel (Drag right edge)</div>
|
|
73
|
+
{ResizableSplitter.getSplitter('#splitter-demo-box', true, true)}
|
|
74
|
+
</div>
|
|
75
|
+
`,
|
|
76
|
+
};
|
|
@@ -63,7 +63,7 @@ export class ResizableSplitter {
|
|
|
63
63
|
backgroundColor: '#ccc',
|
|
64
64
|
},
|
|
65
65
|
};
|
|
66
|
-
bindGlobalStyle('resizable-splitter', css);
|
|
66
|
+
bindGlobalStyle('resizable-splitter', css, false, true);
|
|
67
67
|
|
|
68
68
|
window.addEventListener('mousemove', ResizableSplitter.onMousemove.bind(ResizableSplitter), false);
|
|
69
69
|
document.documentElement.addEventListener('mouseup', ResizableSplitter.onMouseup.bind(ResizableSplitter), false);
|
|
@@ -105,14 +105,14 @@ export class ResizableSplitter {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
static getSplitter(selector: string, isVertical: boolean, isRightOrTop: boolean) {
|
|
108
|
+
if (!this.initialized) {
|
|
109
|
+
this.initialized = true;
|
|
110
|
+
this.init();
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
const className = this.getSplitterClassName(isVertical, isRightOrTop);
|
|
109
114
|
|
|
110
115
|
const onMousedown = (event: any) => {
|
|
111
|
-
if (!this.initialized) {
|
|
112
|
-
this.initialized = true;
|
|
113
|
-
this.init();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
116
|
ResizableSplitter.hostNode = document.querySelector(selector)!;
|
|
117
117
|
if (!ResizableSplitter.hostNode) {
|
|
118
118
|
console.error(`Can't find element: ${selector}`);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { SelectAngleComponent, SelectAngleComponentProps } from './select-angle-component';
|
|
3
|
+
|
|
4
|
+
export const selectAngleDemo: DemoStory<SelectAngleComponentProps> = {
|
|
5
|
+
id: 'select-angle-demo',
|
|
6
|
+
text: 'Select Angle Demo',
|
|
7
|
+
args: {
|
|
8
|
+
size: '100px',
|
|
9
|
+
angle: 45,
|
|
10
|
+
onChange: () => {},
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
size: { control: 'text', description: 'Size of the dial container' },
|
|
14
|
+
angle: { control: 'number', description: 'Initial angle (0-360)' },
|
|
15
|
+
},
|
|
16
|
+
render: (args) => {
|
|
17
|
+
return (
|
|
18
|
+
<div style={{ padding: '20px' }}>
|
|
19
|
+
<p style={{ color: '#666', marginBottom: '16px' }}>Drag the needle or click the edge dots to set the angle.</p>
|
|
20
|
+
<SelectAngleComponent {...args} onChange={(val) => console.log('Angle changed:', val)} />
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
},
|
|
24
|
+
code: `import { SelectAngleComponent } from 'lupine.components/components/select-angle-component';
|
|
25
|
+
|
|
26
|
+
<SelectAngleComponent
|
|
27
|
+
size="100px"
|
|
28
|
+
angle={45}
|
|
29
|
+
onChange={(val) => console.log('Angle changed:', val)}
|
|
30
|
+
/>
|
|
31
|
+
`,
|
|
32
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { SelectWithTitle, SelectOptionProps } from './select-with-title';
|
|
3
|
+
|
|
4
|
+
export const selectWithTitleDemo: DemoStory<any> = {
|
|
5
|
+
id: 'select-with-title-demo',
|
|
6
|
+
text: 'Select With Title Demo',
|
|
7
|
+
args: {
|
|
8
|
+
title: 'Choose a fruit',
|
|
9
|
+
size: 1,
|
|
10
|
+
width: '200px',
|
|
11
|
+
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
title: { control: 'text', description: 'Title text shown above' },
|
|
14
|
+
size: { control: 'number', description: 'HTML select size attribute' },
|
|
15
|
+
width: { control: 'text', description: 'Width of the select' },
|
|
16
|
+
},
|
|
17
|
+
render: (args) => {
|
|
18
|
+
const options: SelectOptionProps[] = [
|
|
19
|
+
{ option: 'Apple', value: 'apple' },
|
|
20
|
+
{ option: 'Banana', value: 'banana', selected: true },
|
|
21
|
+
{ option: 'Cherry', value: 'cherry' },
|
|
22
|
+
];
|
|
23
|
+
return (
|
|
24
|
+
<div style={{ padding: '20px' }}>
|
|
25
|
+
{SelectWithTitle(
|
|
26
|
+
args.title,
|
|
27
|
+
options,
|
|
28
|
+
(val) => console.log('Selected:', val),
|
|
29
|
+
args.size,
|
|
30
|
+
'input-base',
|
|
31
|
+
args.width
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
code: `import { SelectWithTitle, SelectOptionProps } from 'lupine.components/components/select-with-title';
|
|
37
|
+
|
|
38
|
+
const options: SelectOptionProps[] = [
|
|
39
|
+
{ option: 'Apple', value: 'apple' },
|
|
40
|
+
{ option: 'Banana', value: 'banana', selected: true },
|
|
41
|
+
{ option: 'Cherry', value: 'cherry' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
{SelectWithTitle(
|
|
45
|
+
'Choose a fruit', // title
|
|
46
|
+
options, // options array
|
|
47
|
+
(val) => console.log('Selected:', val), // onChange
|
|
48
|
+
1, // size
|
|
49
|
+
'input-base', // className
|
|
50
|
+
'200px' // width
|
|
51
|
+
)}
|
|
52
|
+
`,
|
|
53
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { Spinner01, Spinner02, Spinner03, SpinnerSize } from './spinner';
|
|
3
|
+
|
|
4
|
+
export const spinnerDemo: DemoStory<any> = {
|
|
5
|
+
id: 'spinner-demo',
|
|
6
|
+
text: 'Spinner Demo',
|
|
7
|
+
args: {
|
|
8
|
+
size: SpinnerSize.Medium,
|
|
9
|
+
color: '#0a74c9',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
size: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
options: Object.values(SpinnerSize),
|
|
15
|
+
description: 'Size of the spinner',
|
|
16
|
+
},
|
|
17
|
+
color: {
|
|
18
|
+
control: 'text',
|
|
19
|
+
description: 'Color of the spinner (Hex, RGB, or var)',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
render: (args) => {
|
|
23
|
+
return (
|
|
24
|
+
<div style={{ display: 'flex', gap: '40px', alignItems: 'center', padding: '20px' }}>
|
|
25
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
|
26
|
+
<Spinner01 size={args.size} color={args.color} />
|
|
27
|
+
<span>Spinner01</span>
|
|
28
|
+
</div>
|
|
29
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
|
30
|
+
<Spinner02 size={args.size} color={args.color} />
|
|
31
|
+
<span>Spinner02</span>
|
|
32
|
+
</div>
|
|
33
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
|
34
|
+
{/* Spinner03 expects an RGB tuple string without the rgb() wrapper */}
|
|
35
|
+
<Spinner03 size={args.size} colorRGB='10 116 201' />
|
|
36
|
+
<span>Spinner03</span>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
code: `import { Spinner01, Spinner02, Spinner03, SpinnerSize } from 'lupine.components/components/spinner';
|
|
42
|
+
|
|
43
|
+
{/* Spinner01 */}
|
|
44
|
+
<Spinner01 size={SpinnerSize.Medium} color="#0a74c9" />
|
|
45
|
+
|
|
46
|
+
{/* Spinner02 */}
|
|
47
|
+
<Spinner02 size={SpinnerSize.Medium} color="#0a74c9" />
|
|
48
|
+
|
|
49
|
+
{/* Spinner03 expects an RGB tuple string without the rgb() wrapper */}
|
|
50
|
+
<Spinner03 size={SpinnerSize.Medium} colorRGB="10 116 201" />
|
|
51
|
+
`,
|
|
52
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { StarsComponent, StarsComponentProps } from './stars-component';
|
|
3
|
+
|
|
4
|
+
export const starsDemo: DemoStory<StarsComponentProps> = {
|
|
5
|
+
id: 'stars-demo',
|
|
6
|
+
text: 'Stars Component Demo',
|
|
7
|
+
args: {
|
|
8
|
+
maxLength: 5,
|
|
9
|
+
value: 3,
|
|
10
|
+
fontSize: '30px',
|
|
11
|
+
fullIcon: <div class='ifc-icon full'>★</div>,
|
|
12
|
+
outlineIcon: <div class='ifc-icon outline'>☆</div>,
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
maxLength: { control: 'number', description: 'Total number of stars' },
|
|
16
|
+
value: { control: 'number', description: 'Current rating value' },
|
|
17
|
+
fontSize: { control: 'text', description: 'Size of the stars (e.g., 20px, 2rem)' },
|
|
18
|
+
},
|
|
19
|
+
render: (args: StarsComponentProps) => {
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ padding: '20px' }}>
|
|
22
|
+
<StarsComponent {...args} />
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
code: `import { StarsComponent } from 'lupine.components/components/stars-component';
|
|
27
|
+
|
|
28
|
+
<StarsComponent
|
|
29
|
+
maxLength={5}
|
|
30
|
+
value={3}
|
|
31
|
+
fontSize="30px"
|
|
32
|
+
fullIcon={<div class="ifc-icon full">★</div>}
|
|
33
|
+
outlineIcon={<div class="ifc-icon outline">☆</div>}
|
|
34
|
+
/>
|
|
35
|
+
`,
|
|
36
|
+
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { bindGlobalStyle, CssProps, RefProps } from 'lupine.components';
|
|
1
|
+
import { bindGlobalStyle, CssProps, RefProps, VNode } from 'lupine.components';
|
|
2
2
|
|
|
3
|
+
/*
|
|
4
|
+
ma-cards-heart and ma-cards-heart-outline are font icons
|
|
5
|
+
*/
|
|
3
6
|
export type StarsHookComponentProps = {
|
|
4
7
|
setValue: (value: number) => void;
|
|
5
8
|
getValue: () => number;
|
|
@@ -10,6 +13,8 @@ export type StarsComponentProps = {
|
|
|
10
13
|
onChange?: (value: number) => void;
|
|
11
14
|
hook?: StarsHookComponentProps;
|
|
12
15
|
fontSize?: string;
|
|
16
|
+
fullIcon?: VNode<any>; // should contain full classname
|
|
17
|
+
outlineIcon?: VNode<any>; // should contain outline classname
|
|
13
18
|
};
|
|
14
19
|
export const StarsComponent = (props: StarsComponentProps) => {
|
|
15
20
|
const css: CssProps = {
|
|
@@ -46,6 +51,9 @@ export const StarsComponent = (props: StarsComponentProps) => {
|
|
|
46
51
|
};
|
|
47
52
|
props.hook.getValue = () => props.value;
|
|
48
53
|
}
|
|
54
|
+
|
|
55
|
+
const fullIcon = props.fullIcon || <i class='ifc-icon ma-cards-heart full'></i>;
|
|
56
|
+
const outlineIcon = props.outlineIcon || <i class='ifc-icon ma-cards-heart-outline outline'></i>;
|
|
49
57
|
const ref: RefProps = {};
|
|
50
58
|
return (
|
|
51
59
|
<div style={{ fontSize: props.fontSize || '20px' }} ref={ref} class='stars-box'>
|
|
@@ -57,8 +65,8 @@ export const StarsComponent = (props: StarsComponentProps) => {
|
|
|
57
65
|
props.onChange?.(index + 1);
|
|
58
66
|
}}
|
|
59
67
|
>
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
{fullIcon}
|
|
69
|
+
{outlineIcon}
|
|
62
70
|
</label>
|
|
63
71
|
))}
|
|
64
72
|
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { SwitchOptionComponent, SwitchOptionComponentProps } from './switch-option-component';
|
|
3
|
+
|
|
4
|
+
export const switchOptionDemo: DemoStory<SwitchOptionComponentProps> = {
|
|
5
|
+
id: 'switch-option-demo',
|
|
6
|
+
text: 'Switch Option Demo',
|
|
7
|
+
args: {
|
|
8
|
+
option1: 'Day',
|
|
9
|
+
option2: 'Night',
|
|
10
|
+
defaultOption: 'Day',
|
|
11
|
+
fontSize: '14px',
|
|
12
|
+
},
|
|
13
|
+
argTypes: {
|
|
14
|
+
option1: { control: 'text', description: 'First option text' },
|
|
15
|
+
option2: { control: 'text', description: 'Second option text' },
|
|
16
|
+
defaultOption: { control: 'text', description: 'Initial selected option' },
|
|
17
|
+
fontSize: { control: 'text', description: 'Font size' },
|
|
18
|
+
},
|
|
19
|
+
render: (args) => {
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ padding: '20px' }}>
|
|
22
|
+
<SwitchOptionComponent {...args} onChange={(val) => console.log('Switched to:', val)} />
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
code: `import { SwitchOptionComponent } from 'lupine.components/components/switch-option-component';
|
|
27
|
+
|
|
28
|
+
<SwitchOptionComponent
|
|
29
|
+
option1="Day"
|
|
30
|
+
option2="Night"
|
|
31
|
+
defaultOption="Day"
|
|
32
|
+
fontSize="14px"
|
|
33
|
+
onChange={(val) => console.log('Switched to:', val)}
|
|
34
|
+
/>
|
|
35
|
+
`,
|
|
36
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { Tabs } from './tabs';
|
|
3
|
+
|
|
4
|
+
export const tabsDemo: DemoStory<any> = {
|
|
5
|
+
id: 'tabs-demo',
|
|
6
|
+
text: 'Tabs Demo',
|
|
7
|
+
args: {
|
|
8
|
+
defaultIndex: 0,
|
|
9
|
+
pagePadding: '16px',
|
|
10
|
+
},
|
|
11
|
+
argTypes: {
|
|
12
|
+
defaultIndex: { control: 'number', description: 'Index of the active tab on load' },
|
|
13
|
+
pagePadding: { control: 'text', description: 'Padding inside each tab page' },
|
|
14
|
+
},
|
|
15
|
+
render: (args) => {
|
|
16
|
+
return (
|
|
17
|
+
<div style={{ height: '300px', width: '500px', border: '1px solid #ccc' }}>
|
|
18
|
+
<Tabs
|
|
19
|
+
defaultIndex={args.defaultIndex}
|
|
20
|
+
pagePadding={args.pagePadding}
|
|
21
|
+
pages={[
|
|
22
|
+
{ title: 'Tab 1', page: <div>Content for Tab 1</div> },
|
|
23
|
+
{ title: 'Tab 2', page: <div>Content for Tab 2</div> },
|
|
24
|
+
{ title: 'Tab 3', page: <div style={{ color: 'red' }}>Content for Tab 3</div> },
|
|
25
|
+
]}
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
code: `import { Tabs } from 'lupine.components/components/tabs';
|
|
31
|
+
|
|
32
|
+
<Tabs
|
|
33
|
+
defaultIndex={0}
|
|
34
|
+
pagePadding="16px"
|
|
35
|
+
pages={[
|
|
36
|
+
{ title: 'Tab 1', page: <div>Content for Tab 1</div> },
|
|
37
|
+
{ title: 'Tab 2', page: <div>Content for Tab 2</div> },
|
|
38
|
+
{ title: 'Tab 3', page: <div style={{ color: 'red' }}>Content for Tab 3</div> },
|
|
39
|
+
]}
|
|
40
|
+
/>
|
|
41
|
+
`,
|
|
42
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { TextGlow, TextGlowProps } from './text-glow';
|
|
3
|
+
|
|
4
|
+
export const textGlowDemo: DemoStory<TextGlowProps> = {
|
|
5
|
+
id: 'text-glow-demo',
|
|
6
|
+
text: 'Text Glow Demo',
|
|
7
|
+
args: {
|
|
8
|
+
text: 'NEON GLOW',
|
|
9
|
+
color: '#ffffff',
|
|
10
|
+
fontSize: '40px',
|
|
11
|
+
padding: '30px',
|
|
12
|
+
fontWeight: 'bold',
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
text: { control: 'text', description: 'The text to animate' },
|
|
16
|
+
color: { control: 'text', description: 'Color of the base text' },
|
|
17
|
+
fontSize: { control: 'text', description: 'Font size' },
|
|
18
|
+
padding: { control: 'text', description: 'Padding around text' },
|
|
19
|
+
fontWeight: { control: 'text', description: 'Font weight' },
|
|
20
|
+
},
|
|
21
|
+
render: (args) => {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
style={{
|
|
25
|
+
display: 'flex',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
height: '200px',
|
|
29
|
+
backgroundColor: '#111',
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<TextGlow {...args} />
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
code: `import { TextGlow } from 'lupine.components/components/text-glow';
|
|
37
|
+
|
|
38
|
+
<TextGlow
|
|
39
|
+
text="NEON GLOW"
|
|
40
|
+
color="#ffffff"
|
|
41
|
+
fontSize="40px"
|
|
42
|
+
padding="30px"
|
|
43
|
+
fontWeight="bold"
|
|
44
|
+
/>
|
|
45
|
+
`,
|
|
46
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { TextScale, TextScaleProps } from './text-scale';
|
|
3
|
+
|
|
4
|
+
export const textScaleDemo: DemoStory<TextScaleProps> = {
|
|
5
|
+
id: 'text-scale-demo',
|
|
6
|
+
text: 'Text Scale Demo',
|
|
7
|
+
args: {
|
|
8
|
+
text: 'Scaling Text!!!',
|
|
9
|
+
color: '#22b8ff',
|
|
10
|
+
backgroundColor: '#a1ffe8',
|
|
11
|
+
fontSize: '35px',
|
|
12
|
+
padding: '15px 30px',
|
|
13
|
+
fontWeight: 'bold',
|
|
14
|
+
},
|
|
15
|
+
argTypes: {
|
|
16
|
+
text: { control: 'text', description: 'The text to animate' },
|
|
17
|
+
color: { control: 'text', description: 'Color of the text' },
|
|
18
|
+
backgroundColor: { control: 'text', description: 'Background color behind text' },
|
|
19
|
+
fontSize: { control: 'text', description: 'Font size' },
|
|
20
|
+
padding: { control: 'text', description: 'Padding around background' },
|
|
21
|
+
fontWeight: { control: 'text', description: 'Font weight' },
|
|
22
|
+
},
|
|
23
|
+
render: (args) => {
|
|
24
|
+
return (
|
|
25
|
+
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '200px' }}>
|
|
26
|
+
<TextScale {...args} />
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
code: `import { TextScale } from 'lupine.components/components/text-scale';
|
|
31
|
+
|
|
32
|
+
<TextScale
|
|
33
|
+
text="Scaling Text!!!"
|
|
34
|
+
color="#22b8ff"
|
|
35
|
+
backgroundColor="#a1ffe8"
|
|
36
|
+
fontSize="35px"
|
|
37
|
+
padding="15px 30px"
|
|
38
|
+
fontWeight="bold"
|
|
39
|
+
/>
|
|
40
|
+
`,
|
|
41
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DemoStory } from '../demo/demo-types';
|
|
2
|
+
import { TextWave, TextLoadingProps } from './text-wave';
|
|
3
|
+
|
|
4
|
+
export const textWaveDemo: DemoStory<TextLoadingProps> = {
|
|
5
|
+
id: 'text-wave-demo',
|
|
6
|
+
text: 'Text Wave Demo',
|
|
7
|
+
args: {
|
|
8
|
+
text: 'Loading...',
|
|
9
|
+
color: '#22b8ff',
|
|
10
|
+
fontSize: '30px',
|
|
11
|
+
padding: '20px',
|
|
12
|
+
fontWeight: 'bold',
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
text: { control: 'text', description: 'The text to animate' },
|
|
16
|
+
color: { control: 'text', description: 'Color of the text' },
|
|
17
|
+
fontSize: { control: 'text', description: 'Font size' },
|
|
18
|
+
padding: { control: 'text', description: 'Padding around text' },
|
|
19
|
+
fontWeight: { control: 'text', description: 'Font weight' },
|
|
20
|
+
},
|
|
21
|
+
render: (args) => {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
style={{
|
|
25
|
+
display: 'flex',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
alignItems: 'center',
|
|
28
|
+
height: '200px',
|
|
29
|
+
backgroundColor: '#f0f0f0',
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<TextWave {...args} />
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
code: `import { TextWave } from 'lupine.components/components/text-wave';
|
|
37
|
+
|
|
38
|
+
<TextWave
|
|
39
|
+
text="Loading..."
|
|
40
|
+
color="#22b8ff"
|
|
41
|
+
fontSize="30px"
|
|
42
|
+
padding="20px"
|
|
43
|
+
fontWeight="bold"
|
|
44
|
+
/>
|
|
45
|
+
`,
|
|
46
|
+
};
|