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.
Files changed (44) hide show
  1. package/package.json +1 -1
  2. package/src/components/action-sheet-demo.tsx +105 -0
  3. package/src/components/button-demo.tsx +33 -0
  4. package/src/components/button-push-animation-demo.tsx +32 -0
  5. package/src/components/button-push-animation.tsx +8 -4
  6. package/src/components/editable-label-demo.tsx +33 -0
  7. package/src/components/input-with-title-demo.tsx +42 -0
  8. package/src/components/message-box-demo.tsx +107 -0
  9. package/src/components/modal-demo.tsx +56 -0
  10. package/src/components/notice-message-demo.tsx +60 -0
  11. package/src/components/popup-menu-demo.tsx +68 -0
  12. package/src/components/popup-menu.tsx +1 -1
  13. package/src/components/progress-demo.tsx +63 -0
  14. package/src/components/progress.tsx +3 -3
  15. package/src/components/radio-label-demo.tsx +41 -0
  16. package/src/components/redirect-demo.tsx +36 -0
  17. package/src/components/resizable-splitter-demo.tsx +76 -0
  18. package/src/components/resizable-splitter.tsx +6 -6
  19. package/src/components/select-angle-demo.tsx +32 -0
  20. package/src/components/select-with-title-demo.tsx +53 -0
  21. package/src/components/spinner-demo.tsx +52 -0
  22. package/src/components/stars-component-demo.tsx +36 -0
  23. package/src/components/stars-component.tsx +11 -3
  24. package/src/components/switch-option-demo.tsx +36 -0
  25. package/src/components/tabs-demo.tsx +42 -0
  26. package/src/components/text-glow-demo.tsx +46 -0
  27. package/src/components/text-scale-demo.tsx +41 -0
  28. package/src/components/text-wave-demo.tsx +46 -0
  29. package/src/components/toggle-button-demo.tsx +42 -0
  30. package/src/components/toggle-play-button-demo.tsx +56 -0
  31. package/src/components/toggle-switch-demo.tsx +43 -0
  32. package/src/demo/demo-about.tsx +12 -0
  33. package/src/demo/demo-container.tsx +57 -0
  34. package/src/demo/demo-css.tsx +3 -0
  35. package/src/demo/demo-frame-helper.tsx +395 -0
  36. package/src/demo/demo-frame.tsx +139 -0
  37. package/src/demo/demo-index.tsx +17 -0
  38. package/src/demo/demo-page.tsx +198 -0
  39. package/src/demo/demo-registry.ts +54 -0
  40. package/src/demo/demo-render-page.tsx +77 -0
  41. package/src/demo/demo-types.ts +22 -0
  42. package/src/html-editor/buttons_morden.gif +0 -0
  43. package/src/html-editor/h-editor.ts +817 -0
  44. 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: number, totalChunks: number) => void;
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: number, totalChunks: number) => {
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 = `${1 - percentage}%`;
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
- <i class='ifc-icon ma-cards-heart full'></i>
61
- <i class='ifc-icon ma-cards-heart-outline outline'></i>
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
+ };