lupine.components 1.1.21 → 1.1.22

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 +87 -0
  3. package/src/components/button-demo.tsx +24 -0
  4. package/src/components/button-push-animation-demo.tsx +24 -0
  5. package/src/components/button-push-animation.tsx +8 -4
  6. package/src/components/editable-label-demo.tsx +25 -0
  7. package/src/components/input-with-title-demo.tsx +31 -0
  8. package/src/components/message-box-demo.tsx +80 -0
  9. package/src/components/modal-demo.tsx +44 -0
  10. package/src/components/notice-message-demo.tsx +52 -0
  11. package/src/components/popup-menu-demo.tsx +49 -0
  12. package/src/components/popup-menu.tsx +1 -1
  13. package/src/components/progress-demo.tsx +51 -0
  14. package/src/components/progress.tsx +3 -3
  15. package/src/components/radio-label-demo.tsx +27 -0
  16. package/src/components/redirect-demo.tsx +28 -0
  17. package/src/components/resizable-splitter-demo.tsx +68 -0
  18. package/src/components/resizable-splitter.tsx +6 -6
  19. package/src/components/select-angle-demo.tsx +24 -0
  20. package/src/components/select-with-title-demo.tsx +36 -0
  21. package/src/components/spinner-demo.tsx +41 -0
  22. package/src/components/stars-component-demo.tsx +26 -0
  23. package/src/components/stars-component.tsx +11 -3
  24. package/src/components/switch-option-demo.tsx +26 -0
  25. package/src/components/tabs-demo.tsx +30 -0
  26. package/src/components/text-glow-demo.tsx +36 -0
  27. package/src/components/text-scale-demo.tsx +30 -0
  28. package/src/components/text-wave-demo.tsx +36 -0
  29. package/src/components/toggle-button-demo.tsx +32 -0
  30. package/src/components/toggle-play-button-demo.tsx +44 -0
  31. package/src/components/toggle-switch-demo.tsx +33 -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 +14 -0
  38. package/src/demo/demo-page.tsx +138 -0
  39. package/src/demo/demo-registry.ts +54 -0
  40. package/src/demo/demo-render-page.tsx +54 -0
  41. package/src/demo/demo-types.ts +21 -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lupine.components",
3
- "version": "1.1.21",
3
+ "version": "1.1.22",
4
4
  "license": "MIT",
5
5
  "author": "uuware.com",
6
6
  "homepage": "https://github.com/uuware/lupine.js",
@@ -0,0 +1,87 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import {
3
+ ActionSheet,
4
+ ActionSheetSelect,
5
+ ActionSheetMessage,
6
+ ActionSheetInput,
7
+ ActionSheetSelectOptionsProps,
8
+ } from './action-sheet';
9
+ import { Button, ButtonSize } from './button';
10
+
11
+ export const actionSheetDemo: DemoStory<any> = {
12
+ id: 'action-sheet-demo',
13
+ text: 'Action Sheet Demo',
14
+ args: {
15
+ title: 'Select an Action',
16
+ confirmButtonText: 'Confirm Option',
17
+ cancelButtonText: 'Cancel Action',
18
+ },
19
+ argTypes: {
20
+ title: { control: 'text', description: 'Title of the action sheet' },
21
+ confirmButtonText: { control: 'text', description: 'Confirm button text' },
22
+ cancelButtonText: { control: 'text', description: 'Cancel button text' },
23
+ },
24
+ render: (args) => {
25
+ return (
26
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '20px', padding: '20px' }}>
27
+ <Button
28
+ text='Show Simple Action Sheet'
29
+ size={ButtonSize.Medium}
30
+ onClick={() => {
31
+ ActionSheet.show({
32
+ title: args.title,
33
+ children: <div style={{ padding: '20px' }}>Custom Content Here</div>,
34
+ confirmButtonText: args.confirmButtonText,
35
+ cancelButtonText: args.cancelButtonText,
36
+ handleConfirmClicked: (close) => close('confirm'),
37
+ });
38
+ }}
39
+ />
40
+ <Button
41
+ text='Show Action Sheet Select'
42
+ size={ButtonSize.Medium}
43
+ onClick={() => {
44
+ ActionSheetSelect.show({
45
+ title: args.title,
46
+ options: ['Option A', 'Option B', 'Option C'],
47
+ confirmButtonText: args.confirmButtonText,
48
+ cancelButtonText: args.cancelButtonText,
49
+ handleClicked: (index, close) => {
50
+ console.log('Selected index:', index);
51
+ close('select');
52
+ },
53
+ });
54
+ }}
55
+ />
56
+ <Button
57
+ text='Show Action Sheet Message'
58
+ size={ButtonSize.Medium}
59
+ onClick={() => {
60
+ ActionSheetMessage.show({
61
+ title: args.title,
62
+ message: 'This is a detailed message shown inside the action sheet.',
63
+ confirmButtonText: args.confirmButtonText,
64
+ cancelButtonText: args.cancelButtonText,
65
+ });
66
+ }}
67
+ />
68
+ <Button
69
+ text='Show Action Sheet Input'
70
+ size={ButtonSize.Medium}
71
+ onClick={() => {
72
+ ActionSheetInput.show({
73
+ title: args.title,
74
+ defaultValue: 'Default text',
75
+ confirmButtonText: args.confirmButtonText,
76
+ cancelButtonText: args.cancelButtonText,
77
+ handleConfirmValue: (val, close) => {
78
+ console.log('Input value:', val);
79
+ close('confirm');
80
+ },
81
+ });
82
+ }}
83
+ />
84
+ </div>
85
+ );
86
+ },
87
+ };
@@ -0,0 +1,24 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { Button, ButtonProps, ButtonSize } from './button';
3
+
4
+ export const buttonDemo: DemoStory<ButtonProps> = {
5
+ id: 'button-demo',
6
+ text: 'Button Demo',
7
+ args: {
8
+ text: 'Click Me',
9
+ size: ButtonSize.Medium,
10
+ disabled: false,
11
+ },
12
+ argTypes: {
13
+ text: { control: 'text', description: 'The text displayed inside the button' },
14
+ size: {
15
+ control: 'select',
16
+ options: Object.values(ButtonSize),
17
+ description: 'The size of the button',
18
+ },
19
+ disabled: { control: 'boolean', description: 'Whether the button is disabled' },
20
+ },
21
+ render: (args: ButtonProps) => {
22
+ return <Button {...args} />;
23
+ },
24
+ };
@@ -0,0 +1,24 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { ButtonPushAnimation, ButtonPushAnimationProps, ButtonPushAnimationSize } from './button-push-animation';
3
+
4
+ export const buttonPushAnimationDemo: DemoStory<ButtonPushAnimationProps> = {
5
+ id: 'button-push-animation-demo',
6
+ text: 'Button Push Animation Demo',
7
+ args: {
8
+ text: 'Push Me',
9
+ size: ButtonPushAnimationSize.Medium,
10
+ disabled: false,
11
+ },
12
+ argTypes: {
13
+ text: { control: 'text', description: 'The text displayed inside the button' },
14
+ size: {
15
+ control: 'select',
16
+ options: Object.values(ButtonPushAnimationSize),
17
+ description: 'The size of the button',
18
+ },
19
+ disabled: { control: 'boolean', description: 'Whether the button is disabled' },
20
+ },
21
+ render: (args: ButtonPushAnimationProps) => {
22
+ return <ButtonPushAnimation {...args} />;
23
+ },
24
+ };
@@ -86,6 +86,10 @@ export const ButtonPushAnimation = (props: ButtonPushAnimationProps) => {
86
86
  textShadow: 'rgba(0, 0, 0, 0.1) 0 0 0.1em',
87
87
  userSelect: 'none',
88
88
  },
89
+ '&:disabled .button-inner span': {
90
+ backgroundImage: 'linear-gradient(135deg, rgba(150, 150, 150, 1), rgba(200, 200, 200, 1))',
91
+ opacity: 0.7,
92
+ },
89
93
  '&.button-ss': {
90
94
  borderRadius: '2px',
91
95
  },
@@ -114,17 +118,17 @@ export const ButtonPushAnimation = (props: ButtonPushAnimationProps) => {
114
118
  padding: '0.5rem 1.5rem',
115
119
  fontSize: '2rem',
116
120
  },
117
- '&:active .button-outer': {
121
+ '&:active:not(:disabled) .button-outer': {
118
122
  boxShadow: '0 0 0 0 rgba(5, 5, 5, 1), 0 0 0 0 rgba(5, 5, 5, 0.5), 0 0 0 0 rgba(5, 5, 5, 0.25)',
119
123
  },
120
- '&:active .button-inner': {
124
+ '&:active:not(:disabled) .button-inner': {
121
125
  boxShadow:
122
126
  '0.1em 0.15em 0.05em 0 inset rgba(5, 5, 5, 0.75), -0.025em -0.03em 0.05em 0.025em inset rgba(5, 5, 5, 0.5), 0.25em 0.25em 0.2em 0 inset rgba(5, 5, 5, 0.5), 0 0 0.05em 0.5em inset rgba(255, 255, 255, 0.15), 0 0 0 0 inset rgba(255, 255, 255, 1), 0.12em 0.12em 0.12em inset rgba(255, 255, 255, 0.25), -0.075em -0.12em 0.2em 0.1em inset rgba(5, 5, 5, 0.25)',
123
127
  },
124
- '&:hover .button-inner': {
128
+ '&:hover:not(:disabled) .button-inner': {
125
129
  transform: 'scale(0.99)',
126
130
  },
127
- '&:hover .button-inner span': {
131
+ '&:hover:not(:disabled) .button-inner span': {
128
132
  transform: 'scale(0.975)',
129
133
  },
130
134
  ...props.css,
@@ -0,0 +1,25 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { EditableLabel, EditableLabelProps } from './editable-label';
3
+
4
+ export const editableLabelDemo: DemoStory<EditableLabelProps> = {
5
+ id: 'editable-label-demo',
6
+ text: 'Editable Label Demo',
7
+ args: {
8
+ text: 'Double click to edit me!',
9
+ mandtory: false,
10
+ },
11
+ argTypes: {
12
+ text: { control: 'text', description: 'Initial text content' },
13
+ mandtory: { control: 'boolean', description: 'If true, value cannot be left empty' },
14
+ },
15
+ render: (args: EditableLabelProps) => {
16
+ return (
17
+ <div style={{ padding: '20px', width: '300px' }}>
18
+ <p style={{ color: '#666', fontSize: '13px', marginBottom: '10px' }}>
19
+ Instructions: Double-click the text below to switch to edit mode. Press Enter to save, or Escape to cancel.
20
+ </p>
21
+ <EditableLabel {...args} save={(val) => console.log('Saved:', val)} />
22
+ </div>
23
+ );
24
+ },
25
+ };
@@ -0,0 +1,31 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { InputWithTitle } from './input-with-title';
3
+
4
+ export const inputWithTitleDemo: DemoStory<any> = {
5
+ id: 'input-with-title-demo',
6
+ text: 'Input With Title Demo',
7
+ args: {
8
+ title: 'Enter your name',
9
+ defaultValue: 'John Doe',
10
+ width: '250px',
11
+ },
12
+ argTypes: {
13
+ title: { control: 'text', description: 'Title text shown above input' },
14
+ defaultValue: { control: 'text', description: 'Initial default value' },
15
+ width: { control: 'text', description: 'Width of the input container' },
16
+ },
17
+ render: (args) => {
18
+ return (
19
+ <div style={{ padding: '20px' }}>
20
+ {InputWithTitle(
21
+ args.title,
22
+ args.defaultValue,
23
+ (val) => console.log('Input onChange:', val),
24
+ (val) => console.log('Input onInput:', val),
25
+ 'input-base',
26
+ args.width
27
+ )}
28
+ </div>
29
+ );
30
+ },
31
+ };
@@ -0,0 +1,80 @@
1
+ import { NotificationColor, NotificationMessage } from 'lupine.components';
2
+ import { DemoStory } from '../demo/demo-types';
3
+ import { MessageBox, MessageBoxButtonProps } from './message-box';
4
+ import { Button, ButtonSize } from './button';
5
+
6
+ export const messageBoxDemo: DemoStory<any> = {
7
+ id: 'message-box-demo',
8
+ text: 'MessageBox Demo',
9
+ args: {
10
+ title: 'System Alert',
11
+ contentMinWidth: '300px',
12
+ },
13
+ argTypes: {
14
+ title: { control: 'text', description: 'Title of the MessageBox' },
15
+ contentMinWidth: { control: 'text', description: 'Minimum width of MessageBox' },
16
+ },
17
+ render: (args) => {
18
+ return (
19
+ <div style={{ padding: '20px' }}>
20
+ <p style={{ color: '#666', marginBottom: '20px' }}>Test different button configurations for MessageBox.</p>
21
+
22
+ <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
23
+ <Button
24
+ text='Yes / No Dialog'
25
+ size={ButtonSize.Medium}
26
+ onClick={() => {
27
+ MessageBox.show({
28
+ title: args.title,
29
+ buttonType: MessageBoxButtonProps.YesNo,
30
+ contentMinWidth: args.contentMinWidth,
31
+ children: <div style={{ padding: '20px' }}>Are you sure you want to proceed?</div>,
32
+ handleClicked: (index, close) => {
33
+ const result = index === 0 ? 'Yes' : 'No';
34
+ NotificationMessage.sendMessage('You clicked: ' + result, NotificationColor.Info);
35
+ close();
36
+ },
37
+ });
38
+ }}
39
+ />
40
+
41
+ <Button
42
+ text='Ok / Cancel Dialog'
43
+ size={ButtonSize.Medium}
44
+ onClick={() => {
45
+ MessageBox.show({
46
+ title: args.title,
47
+ buttonType: MessageBoxButtonProps.OkCancel,
48
+ contentMinWidth: args.contentMinWidth,
49
+ children: <div style={{ padding: '20px' }}>Please confirm this action.</div>,
50
+ handleClicked: (index, close) => {
51
+ const result = index === 0 ? 'OK' : 'Cancel';
52
+ const level = index === 0 ? NotificationColor.Success : NotificationColor.Warning;
53
+ NotificationMessage.sendMessage('You clicked: ' + result, level);
54
+ close();
55
+ },
56
+ });
57
+ }}
58
+ />
59
+
60
+ <Button
61
+ text='Ok Only'
62
+ size={ButtonSize.Medium}
63
+ onClick={() => {
64
+ MessageBox.show({
65
+ title: args.title,
66
+ buttonType: MessageBoxButtonProps.Ok,
67
+ contentMinWidth: args.contentMinWidth,
68
+ children: <div style={{ padding: '20px' }}>Operation completed successfully!</div>,
69
+ handleClicked: (index, close) => {
70
+ NotificationMessage.sendMessage('Dialog dismissed', NotificationColor.Success);
71
+ close();
72
+ },
73
+ });
74
+ }}
75
+ />
76
+ </div>
77
+ </div>
78
+ );
79
+ },
80
+ };
@@ -0,0 +1,44 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { ModalWindow } from './modal';
3
+ import { Button, ButtonSize } from './button';
4
+
5
+ export const modalDemo: DemoStory<any> = {
6
+ id: 'modal-demo',
7
+ text: 'Modal Window Demo',
8
+ args: {
9
+ title: 'Example Modal',
10
+ noMoving: true,
11
+ noModal: false,
12
+ contentMinWidth: '300px',
13
+ },
14
+ argTypes: {
15
+ title: { control: 'text', description: 'Title of the modal' },
16
+ noMoving: { control: 'boolean', description: 'Disable dragging?' },
17
+ noModal: { control: 'boolean', description: "If true, it won't block background interaction" },
18
+ contentMinWidth: { control: 'text', description: 'Minimum width of modal' },
19
+ },
20
+ render: (args) => {
21
+ return (
22
+ <div style={{ padding: '20px' }}>
23
+ <Button
24
+ text='Open Modal'
25
+ size={ButtonSize.Medium}
26
+ onClick={() => {
27
+ ModalWindow.show({
28
+ title: args.title,
29
+ children: <div style={{ padding: '20px' }}>This is the modal content!</div>,
30
+ noMoving: args.noMoving,
31
+ noModal: args.noModal,
32
+ contentMinWidth: args.contentMinWidth,
33
+ buttons: ['Cancel', 'Confirm'],
34
+ handleClicked: (ind, close) => {
35
+ console.log('Clicked button:', ind);
36
+ close();
37
+ },
38
+ });
39
+ }}
40
+ />
41
+ </div>
42
+ );
43
+ },
44
+ };
@@ -0,0 +1,52 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { NotificationMessage, NotificationColor } from './notice-message';
3
+ import { Button, ButtonSize } from './button';
4
+
5
+ export const noticeMessageDemo: DemoStory<any> = {
6
+ id: 'notice-message-demo',
7
+ text: 'Notice Message Demo',
8
+ args: {
9
+ message: 'Action completed successfully!',
10
+ permanent: false,
11
+ showTime: 3000,
12
+ },
13
+ argTypes: {
14
+ message: { control: 'text', description: 'Message content' },
15
+ permanent: { control: 'boolean', description: 'If true, stays until manually closed' },
16
+ showTime: { control: 'number', description: 'Time in ms to show (if not permanent)' },
17
+ },
18
+ render: (args) => {
19
+ return (
20
+ <div style={{ padding: '20px', display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
21
+ <Button
22
+ text='Show Info'
23
+ size={ButtonSize.Medium}
24
+ onClick={() =>
25
+ NotificationMessage.sendMessage(args.message, NotificationColor.Info, args.permanent, args.showTime)
26
+ }
27
+ />
28
+ <Button
29
+ text='Show Success'
30
+ size={ButtonSize.Medium}
31
+ onClick={() =>
32
+ NotificationMessage.sendMessage(args.message, NotificationColor.Success, args.permanent, args.showTime)
33
+ }
34
+ />
35
+ <Button
36
+ text='Show Warning'
37
+ size={ButtonSize.Medium}
38
+ onClick={() =>
39
+ NotificationMessage.sendMessage(args.message, NotificationColor.Warning, args.permanent, args.showTime)
40
+ }
41
+ />
42
+ <Button
43
+ text='Show Error'
44
+ size={ButtonSize.Medium}
45
+ onClick={() =>
46
+ NotificationMessage.sendMessage(args.message, NotificationColor.Error, args.permanent, args.showTime)
47
+ }
48
+ />
49
+ </div>
50
+ );
51
+ },
52
+ };
@@ -0,0 +1,49 @@
1
+ import { DemoStory } from '../demo/demo-types';
2
+ import { PopupMenuWithButton, PopupMenuWithLabel, PopupMenuWithIcon } from './popup-menu';
3
+
4
+ export const popupMenuDemo: DemoStory<any> = {
5
+ id: 'popup-menu-demo',
6
+ text: 'Popup Menu Demo',
7
+ args: {
8
+ label: 'Actions',
9
+ defaultValue: 'Select...',
10
+ align: 'right',
11
+ },
12
+ argTypes: {
13
+ label: { control: 'text', description: 'Label for button/text triggers' },
14
+ defaultValue: { control: 'text', description: 'Default selected text' },
15
+ align: { control: 'select', options: ['left', 'right'], description: 'Menu drop alignment' },
16
+ },
17
+ render: (args) => {
18
+ const list = ['Edit Profile', 'Settings', '', 'Log Out'];
19
+ return (
20
+ <div style={{ padding: '20px', display: 'flex', gap: '40px', alignItems: 'flex-start' }}>
21
+ <div>
22
+ <h3>With Button</h3>
23
+ <PopupMenuWithButton
24
+ label={args.label}
25
+ list={list}
26
+ defaultValue={args.defaultValue}
27
+ align={args.align}
28
+ handleSelected={(val: string) => console.log('Selected:', val)}
29
+ />
30
+ </div>
31
+
32
+ <div>
33
+ <h3>With Label</h3>
34
+ <PopupMenuWithLabel label={args.label} list={list} defaultValue={args.defaultValue} align={args.align} />
35
+ </div>
36
+
37
+ <div>
38
+ <h3>With Icon</h3>
39
+ <PopupMenuWithIcon
40
+ list={list}
41
+ defaultValue={args.defaultValue}
42
+ align={args.align}
43
+ icon={<span style={{ fontSize: '24px' }}>⚙️</span>}
44
+ />
45
+ </div>
46
+ </div>
47
+ );
48
+ },
49
+ };
@@ -186,7 +186,7 @@ export const PopupMenu = ({
186
186
  padding: '5px 0px',
187
187
  overflow: 'auto',
188
188
  'line-height': '1.2em',
189
- 'min-width': minWidth || 'auto',
189
+ 'min-width': minWidth || 'max-content',
190
190
  'max-width': maxWidth || '200px',
191
191
  'max-height': maxHeight || '300px',
192
192
  'box-shadow': 'var(--cover-box-shadow)', //'#0000004c 0px 19px 38px, #00000038 0px 15px 12px',
@@ -0,0 +1,51 @@
1
+ import { RefProps } from 'lupine.web';
2
+ import { DemoStory } from '../demo/demo-types';
3
+ import { Progress, ProgressHookProps } from './progress';
4
+
5
+ // Note: Progress uses a singleton-like hook approach internally,
6
+ // so we create a dummy hook object to interact with it.
7
+ const progressHook: ProgressHookProps = {};
8
+
9
+ export const progressDemo: DemoStory<any> = {
10
+ id: 'progress-demo',
11
+ text: 'Progress Demo',
12
+ args: {
13
+ simulate: false,
14
+ },
15
+ argTypes: {
16
+ simulate: {
17
+ control: 'boolean',
18
+ description: 'Check this to simulate a 3-second progress upload',
19
+ },
20
+ },
21
+ render: (args) => {
22
+ const ref: RefProps = {
23
+ onLoad: async () => {
24
+ // If the simulate toggle is flipped, run a fake progression
25
+ if (args.simulate && progressHook.onShow) {
26
+ progressHook.onShow(true, 'Simulating Upload...');
27
+ let p = 0;
28
+ const interval = setInterval(() => {
29
+ p += 3;
30
+ if (p > 100) {
31
+ clearInterval(interval);
32
+ progressHook.onShow!(false);
33
+ } else {
34
+ progressHook.onProgress!(p / 100);
35
+ }
36
+ }, 100);
37
+ } else if (!args.simulate && progressHook.onShow) {
38
+ progressHook.onShow(false);
39
+ }
40
+ },
41
+ };
42
+ return (
43
+ <div ref={ref} style={{ padding: '20px' }}>
44
+ <p style={{ color: '#666' }}>
45
+ Toggle the 'simulate' control to see the fixed progress bar at the bottom of the screen.
46
+ </p>
47
+ <Progress hook={progressHook} />
48
+ </div>
49
+ );
50
+ },
51
+ };
@@ -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,27 @@
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
+ };
@@ -0,0 +1,28 @@
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
+ };