@reni-corp/reni-2c-ui 0.3.28 → 0.3.29

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 (101) hide show
  1. package/README.md +139 -16
  2. package/dist/components/elements/Alert.vue.d.ts +21 -3
  3. package/dist/components/elements/Alert.vue.d.ts.map +1 -1
  4. package/dist/components/elements/CheckBox.vue.d.ts +42 -2
  5. package/dist/components/elements/CheckBox.vue.d.ts.map +1 -1
  6. package/dist/components/elements/ComboBox.vue.d.ts +153 -0
  7. package/dist/components/elements/ComboBox.vue.d.ts.map +1 -0
  8. package/dist/components/elements/Icon.vue.d.ts.map +1 -1
  9. package/dist/components/elements/PasswordField.vue.d.ts +75 -25
  10. package/dist/components/elements/PasswordField.vue.d.ts.map +1 -1
  11. package/dist/components/elements/Progress.vue.d.ts +45 -0
  12. package/dist/components/elements/Progress.vue.d.ts.map +1 -0
  13. package/dist/components/elements/SelectBox.vue.d.ts +30 -10
  14. package/dist/components/elements/SelectBox.vue.d.ts.map +1 -1
  15. package/dist/components/elements/SkeletonLoader.vue.d.ts +30 -0
  16. package/dist/components/elements/SkeletonLoader.vue.d.ts.map +1 -0
  17. package/dist/components/elements/SpinButton.vue.d.ts +4 -2
  18. package/dist/components/elements/SpinButton.vue.d.ts.map +1 -1
  19. package/dist/components/elements/TextField.vue.d.ts +21 -6
  20. package/dist/components/elements/TextField.vue.d.ts.map +1 -1
  21. package/dist/components/features/ProductList.vue.d.ts +4 -0
  22. package/dist/components/features/ProductList.vue.d.ts.map +1 -1
  23. package/dist/components/features/ProductListItem.vue.d.ts +4 -0
  24. package/dist/components/features/ProductListItem.vue.d.ts.map +1 -1
  25. package/dist/components/features/ProductPurchase.vue.d.ts +0 -4
  26. package/dist/components/features/ProductPurchase.vue.d.ts.map +1 -1
  27. package/dist/components/foundation/AppBar.vue.d.ts +28 -3
  28. package/dist/components/foundation/AppBar.vue.d.ts.map +1 -1
  29. package/dist/components/foundation/AppFooter.vue.d.ts +51 -1
  30. package/dist/components/foundation/AppFooter.vue.d.ts.map +1 -1
  31. package/dist/components/interactive/Disclosure.vue.d.ts +54 -0
  32. package/dist/components/interactive/Disclosure.vue.d.ts.map +1 -0
  33. package/dist/components/layouts/Page.vue.d.ts +2 -0
  34. package/dist/components/layouts/Page.vue.d.ts.map +1 -1
  35. package/dist/components/renderless/Form.vue.d.ts +27 -1
  36. package/dist/components/renderless/Form.vue.d.ts.map +1 -1
  37. package/dist/index.d.ts +9 -3
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.es.js +7161 -5941
  40. package/dist/script.es.js +8364 -7146
  41. package/dist/script.umd.js +26 -26
  42. package/dist/style.css +1 -1
  43. package/dist/types.d.ts +7 -0
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/utils.d.ts.map +1 -1
  46. package/package.json +18 -13
  47. package/src/stories/Alert.stories.ts +260 -0
  48. package/src/stories/AnnounceBar.stories.ts +138 -0
  49. package/src/stories/AppBar.stories.ts +277 -0
  50. package/src/stories/AppFooter.stories.ts +274 -0
  51. package/src/stories/AppFrame.stories.ts +46 -0
  52. package/src/stories/AppLayout.stories.ts +870 -0
  53. package/src/stories/Button.stories.ts +101 -0
  54. package/src/stories/Card.stories.ts +152 -0
  55. package/src/stories/Carousel.stories.ts +62 -0
  56. package/src/stories/CarouselBanner.stories.ts +103 -0
  57. package/src/stories/CheckBox.stories.ts +76 -0
  58. package/src/stories/ComboBox.stories.ts +524 -0
  59. package/src/stories/Dialog.stories.ts +174 -0
  60. package/src/stories/Disclosure.stories.ts +217 -0
  61. package/src/stories/Divider.stories.ts +68 -0
  62. package/src/stories/Drawer.stories.ts +135 -0
  63. package/src/stories/DropDown.stories.ts +195 -0
  64. package/src/stories/FloatingBanner.stories.ts +79 -0
  65. package/src/stories/Form.stories.ts +704 -0
  66. package/src/stories/Gallery.stories.ts +78 -0
  67. package/src/stories/Grid.stories.ts +357 -0
  68. package/src/stories/Hero.stories.ts +52 -0
  69. package/src/stories/Html.stories.ts +178 -0
  70. package/src/stories/Icon.stories.ts +176 -0
  71. package/src/stories/Image.stories.ts +613 -0
  72. package/src/stories/Label.stories.ts +54 -0
  73. package/src/stories/List.stories.ts +112 -0
  74. package/src/stories/Modal.stories.ts +123 -0
  75. package/src/stories/Notification.stories.ts +82 -0
  76. package/src/stories/Page.stories.ts +414 -0
  77. package/src/stories/PasswordField.stories.ts +304 -0
  78. package/src/stories/ProductLabels.stories.ts +65 -0
  79. package/src/stories/ProductList.stories.ts +679 -0
  80. package/src/stories/ProductPurchase.stories.ts +807 -0
  81. package/src/stories/Progress.stories.ts +192 -0
  82. package/src/stories/Radio.stories.ts +81 -0
  83. package/src/stories/Section.stories.ts +244 -0
  84. package/src/stories/SelectBox.stories.ts +377 -0
  85. package/src/stories/SkeletonLoader.stories.ts +170 -0
  86. package/src/stories/Slider.stories.ts +79 -0
  87. package/src/stories/SnsLink.stories.ts +259 -0
  88. package/src/stories/SoldStacker.stories.ts +68 -0
  89. package/src/stories/SpinButton.stories.ts +134 -0
  90. package/src/stories/Spinner.stories.ts +58 -0
  91. package/src/stories/Stack.stories.ts +104 -0
  92. package/src/stories/Switch.stories.ts +68 -0
  93. package/src/stories/Tab.stories.ts +52 -0
  94. package/src/stories/TabPanels.stories.ts +67 -0
  95. package/src/stories/Tabs.stories.ts +68 -0
  96. package/src/stories/Text.stories.ts +69 -0
  97. package/src/stories/TextArea.stories.ts +78 -0
  98. package/src/stories/TextField.stories.ts +97 -0
  99. package/src/stories/ToolChip.stories.ts +125 -0
  100. package/dist/components/elements/SkeltonLoader.vue.d.ts +0 -7
  101. package/dist/components/elements/SkeltonLoader.vue.d.ts.map +0 -1
@@ -0,0 +1,78 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import Gallery, { GalleryProps } from '@/components/interactive/Gallery.vue'
3
+ import Stack from '@/components/layouts/Stack.vue'
4
+
5
+ const meta: Meta<typeof Gallery> = {
6
+ title: 'Interactive/Gallery',
7
+ component: Gallery,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ showThumbs: { control: 'boolean' },
11
+ aspect: {
12
+ control: 'select',
13
+ options: [
14
+ 'square',
15
+ 'portrait',
16
+ 'landscape',
17
+ 'widescreen',
18
+ 'widescreen-reverse',
19
+ 'panorama',
20
+ 'panorama-reverse',
21
+ 'cinema',
22
+ 'cinema-reverse',
23
+ 'golden',
24
+ 'golden-reverse',
25
+ ],
26
+ },
27
+ },
28
+ args: {
29
+ showThumbs: true,
30
+ delay: 3000,
31
+ aspect: 'square',
32
+ imageUrls: [
33
+ 'https://auc-pctr.c.yimg.jp/i/auctions.c.yimg.jp/images.auctions.yahoo.co.jp/image/dr000/auc0308/users/625b657f04490ce1548d35633858e8b2399eb171/i-img853x1200-1659348029r2sb8j332226.jpg?pri=l&w=300&h=300&up=0&nf_src=sy&nf_path=images/auc/pc/top/image/1.0.3/na_170x170.png&nf_st=200',
34
+ 'https://www.ell.co.jp/osu108/pic/pre-school.jpg',
35
+ 'https://clubque.net/livereport/03report/img/pre-school5.jpg',
36
+ ],
37
+ },
38
+ }
39
+
40
+ export default meta
41
+ type StoryArgs = GalleryProps
42
+ type Story = StoryObj<StoryArgs>
43
+ type OverridesStory = Omit<Story, 'argTypes'> & {
44
+ argTypes?: Record<string, any>
45
+ }
46
+
47
+ export const 基本: OverridesStory = {
48
+ args: {},
49
+ argTypes: {
50
+ default: { table: { disable: true } },
51
+ },
52
+ render: (args: StoryArgs) => ({
53
+ components: { 'rn-gallery': Gallery, 'rn-stack': Stack },
54
+ setup() {
55
+ return { args }
56
+ },
57
+ template: /* html */ `
58
+ <div class='sb-canvas'>
59
+ <rn-stack
60
+ direction="vertical"
61
+ horizontal-re-size="fill"
62
+ vertical-re-size="fill"
63
+ horizontal-align="center"
64
+ vertical-align="center"
65
+ >
66
+ <div style="width:320px">
67
+ <rn-gallery
68
+ :delay=args.delay
69
+ :aspect=args.aspect
70
+ :show-thumbs=args.showThumbs
71
+ :image-urls=args.imageUrls
72
+ />
73
+ </div>
74
+ </rn-stack>
75
+ </div>
76
+ `,
77
+ }),
78
+ }
@@ -0,0 +1,357 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import Grid, { type GridProps } from '@/components/layouts/Grid.vue'
3
+ import Card from '@/components/layouts/Card.vue'
4
+ import Stack from '@/components/layouts/Stack.vue'
5
+ import Text from '@/components/elements/Text.vue'
6
+
7
+ const meta: Meta<typeof Grid> = {
8
+ title: 'Layouts/Grid',
9
+ component: Grid,
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ column: {
13
+ control: 'select',
14
+ options: [2, 3, 4, 5, 6, 7, 8],
15
+ description: '共通のカラム数',
16
+ },
17
+ pcColumn: {
18
+ control: 'select',
19
+ options: [2, 3, 4, 5, 6, 7, 8],
20
+ description: 'PC向けのカラム数',
21
+ },
22
+ spColumn: {
23
+ control: 'select',
24
+ options: [1, 2, 3],
25
+ description: 'スマートフォン向けのカラム数',
26
+ },
27
+ gap: {
28
+ control: 'select',
29
+ options: ['sm', 'md', 'lg'],
30
+ description: 'アイテム間の間隔',
31
+ },
32
+ },
33
+ args: {
34
+ column: 2,
35
+ pcColumn: undefined,
36
+ spColumn: undefined,
37
+ gap: 'md',
38
+ },
39
+ }
40
+
41
+ export default meta
42
+ type StoryArgs = GridProps
43
+ type Story = StoryObj<StoryArgs>
44
+ type OverridesStory = Omit<Story, 'argTypes'> & {
45
+ argTypes?: Record<string, any>
46
+ }
47
+
48
+ export const 基本: OverridesStory = {
49
+ args: {
50
+ column: 3,
51
+ gap: 'md',
52
+ },
53
+ render: (args: StoryArgs) => ({
54
+ components: { 'rn-grid': Grid, 'rn-card': Card },
55
+ setup() {
56
+ const items = Array.from({ length: 6 }, (_, i) => ({
57
+ id: i + 1,
58
+ title: `アイテム ${i + 1}`,
59
+ content: `これは${i + 1}番目のグリッドアイテムです。`,
60
+ }))
61
+
62
+ return { args, items }
63
+ },
64
+ template: /* html */ `
65
+ <div class='sb-canvas'>
66
+ <rn-grid
67
+ :column="args.column"
68
+ :pc-column="args.pcColumn"
69
+ :sp-column="args.spColumn"
70
+ :gap="args.gap"
71
+ >
72
+ <rn-card
73
+ v-for="item in items"
74
+ :key="item.id"
75
+ :title="item.title"
76
+ elevation
77
+ >
78
+ {{ item.content }}
79
+ </rn-card>
80
+ </rn-grid>
81
+ </div>
82
+ `,
83
+ }),
84
+ }
85
+
86
+ export const レスポンシブ: OverridesStory = {
87
+ args: {
88
+ pcColumn: 4,
89
+ spColumn: 2,
90
+ gap: 'md',
91
+ },
92
+ argTypes: {
93
+ column: { control: { disable: true } },
94
+ pcColumn: { control: { disable: true } },
95
+ spColumn: { control: { disable: true } },
96
+ gap: { control: { disable: true } },
97
+ },
98
+ render: (args: StoryArgs) => ({
99
+ components: {
100
+ 'rn-grid': Grid,
101
+ 'rn-card': Card,
102
+ 'rn-stack': Stack,
103
+ 'rn-text': Text,
104
+ },
105
+ setup() {
106
+ const items = Array.from({ length: 8 }, (_, i) => ({
107
+ id: i + 1,
108
+ title: `商品 ${i + 1}`,
109
+ price: `¥${(i + 1) * 1000}`,
110
+ description: `商品${i + 1}の説明文です。`,
111
+ }))
112
+
113
+ return { args, items }
114
+ },
115
+ template: /* html */ `
116
+ <div class='sb-canvas'>
117
+ <rn-stack direction="vertical" gap="lg">
118
+ <div>
119
+ <h3>レスポンシブグリッド</h3>
120
+ <p>PC: 4カラム / スマートフォン: 2カラム</p>
121
+ <p>ブラウザのウィンドウサイズを変更して確認してください。</p>
122
+ </div>
123
+
124
+ <rn-grid
125
+ :pc-column="args.pcColumn"
126
+ :sp-column="args.spColumn"
127
+ :gap="args.gap"
128
+ >
129
+ <rn-card
130
+ v-for="item in items"
131
+ :key="item.id"
132
+ :title="item.title"
133
+ elevation
134
+ >
135
+ <rn-stack direction="vertical" gap="xs">
136
+ <rn-text size="lg" weight="bold" color="primary">
137
+ {{ item.price }}
138
+ </rn-text>
139
+ <rn-text size="sm" color="subtle">
140
+ {{ item.description }}
141
+ </rn-text>
142
+ </rn-stack>
143
+ </rn-card>
144
+ </rn-grid>
145
+ </rn-stack>
146
+ </div>
147
+ `,
148
+ }),
149
+ }
150
+
151
+ export const 異なるカラム数: OverridesStory = {
152
+ args: {},
153
+ argTypes: {
154
+ column: { control: { disable: true } },
155
+ pcColumn: { control: { disable: true } },
156
+ spColumn: { control: { disable: true } },
157
+ gap: { control: { disable: true } },
158
+ },
159
+ render: (args: StoryArgs) => ({
160
+ components: { 'rn-grid': Grid, 'rn-card': Card, 'rn-stack': Stack },
161
+ setup() {
162
+ const createItems = (count: number) =>
163
+ Array.from({ length: count }, (_, i) => ({
164
+ id: i + 1,
165
+ title: `Item ${i + 1}`,
166
+ }))
167
+
168
+ return { args, createItems }
169
+ },
170
+ template: /* html */ `
171
+ <div class='sb-canvas'>
172
+ <rn-stack direction="vertical" gap="xl">
173
+ <rn-stack direction="vertical" gap="md">
174
+ <h4>2カラム</h4>
175
+ <rn-grid column="2" gap="sm">
176
+ <rn-card
177
+ v-for="item in createItems(4)"
178
+ :key="item.id"
179
+ :title="item.title"
180
+ elevation
181
+ >
182
+ 2カラムのアイテム
183
+ </rn-card>
184
+ </rn-grid>
185
+ </rn-stack>
186
+
187
+ <rn-stack direction="vertical" gap="md">
188
+ <h4>3カラム</h4>
189
+ <rn-grid column="3" gap="md">
190
+ <rn-card
191
+ v-for="item in createItems(6)"
192
+ :key="item.id"
193
+ :title="item.title"
194
+ elevation
195
+ >
196
+ 3カラムのアイテム
197
+ </rn-card>
198
+ </rn-grid>
199
+ </rn-stack>
200
+
201
+ <rn-stack direction="vertical" gap="md">
202
+ <h4>4カラム</h4>
203
+ <rn-grid column="4" gap="lg">
204
+ <rn-card
205
+ v-for="item in createItems(8)"
206
+ :key="item.id"
207
+ :title="item.title"
208
+ elevation
209
+ >
210
+ 4カラムのアイテム
211
+ </rn-card>
212
+ </rn-grid>
213
+ </rn-stack>
214
+ </rn-stack>
215
+ </div>
216
+ `,
217
+ }),
218
+ }
219
+
220
+ export const 間隔の比較: OverridesStory = {
221
+ args: {},
222
+ argTypes: {
223
+ column: { control: { disable: true } },
224
+ pcColumn: { control: { disable: true } },
225
+ spColumn: { control: { disable: true } },
226
+ gap: { control: { disable: true } },
227
+ },
228
+ render: (args: StoryArgs) => ({
229
+ components: { 'rn-grid': Grid, 'rn-card': Card, 'rn-stack': Stack },
230
+ setup() {
231
+ const items = Array.from({ length: 6 }, (_, i) => ({
232
+ id: i + 1,
233
+ title: `Item ${i + 1}`,
234
+ }))
235
+
236
+ return { args, items }
237
+ },
238
+ template: /* html */ `
239
+ <div class='sb-canvas'>
240
+ <rn-stack direction="vertical" gap="xl">
241
+ <rn-stack direction="vertical" gap="md">
242
+ <h4>Gap: Small</h4>
243
+ <rn-grid column="3" gap="sm">
244
+ <rn-card
245
+ v-for="item in items"
246
+ :key="'sm-' + item.id"
247
+ :title="item.title"
248
+ elevation
249
+ >
250
+ 小さい間隔
251
+ </rn-card>
252
+ </rn-grid>
253
+ </rn-stack>
254
+
255
+ <rn-stack direction="vertical" gap="md">
256
+ <h4>Gap: Medium</h4>
257
+ <rn-grid column="3" gap="md">
258
+ <rn-card
259
+ v-for="item in items"
260
+ :key="'md-' + item.id"
261
+ :title="item.title"
262
+ elevation
263
+ >
264
+ 中間の間隔
265
+ </rn-card>
266
+ </rn-grid>
267
+ </rn-stack>
268
+
269
+ <rn-stack direction="vertical" gap="md">
270
+ <h4>Gap: Large</h4>
271
+ <rn-grid column="3" gap="lg">
272
+ <rn-card
273
+ v-for="item in items"
274
+ :key="'lg-' + item.id"
275
+ :title="item.title"
276
+ elevation
277
+ >
278
+ 大きい間隔
279
+ </rn-card>
280
+ </rn-grid>
281
+ </rn-stack>
282
+ </rn-stack>
283
+ </div>
284
+ `,
285
+ }),
286
+ }
287
+
288
+ export const 不均等なコンテンツ: OverridesStory = {
289
+ args: {
290
+ column: 3,
291
+ gap: 'md',
292
+ },
293
+ argTypes: {
294
+ column: { control: { disable: true } },
295
+ gap: { control: { disable: true } },
296
+ },
297
+ render: (args: StoryArgs) => ({
298
+ components: {
299
+ 'rn-grid': Grid,
300
+ 'rn-card': Card,
301
+ 'rn-stack': Stack,
302
+ 'rn-text': Text,
303
+ },
304
+ setup() {
305
+ const items = [
306
+ { id: 1, title: '短いタイトル', content: '短いコンテンツ' },
307
+ {
308
+ id: 2,
309
+ title: 'とても長いタイトルのカード',
310
+ content:
311
+ 'これは非常に長いコンテンツの例です。複数行にわたって表示される可能性があります。グリッドレイアウトでは、各アイテムの高さが異なっていても適切に配置されます。',
312
+ },
313
+ { id: 3, title: '中程度', content: '中程度の長さのコンテンツです。' },
314
+ {
315
+ id: 4,
316
+ title: 'リスト形式',
317
+ content: '• 項目1\n• 項目2\n• 項目3\n• 項目4',
318
+ },
319
+ { id: 5, title: '短い', content: 'コンパクト' },
320
+ {
321
+ id: 6,
322
+ title: '詳細情報カード',
323
+ content:
324
+ 'このカードには詳細な情報が含まれています。グリッドシステムは、コンテンツの高さが異なっても美しくレイアウトを保持します。',
325
+ },
326
+ ]
327
+
328
+ return { args, items }
329
+ },
330
+ template: /* html */ `
331
+ <div class='sb-canvas'>
332
+ <rn-stack direction="vertical" gap="lg">
333
+ <div>
334
+ <h3>不均等なコンテンツのグリッド</h3>
335
+ <p>各カードの高さが異なってもレイアウトが適切に保たれます。</p>
336
+ </div>
337
+
338
+ <rn-grid
339
+ :column="args.column"
340
+ :gap="args.gap"
341
+ >
342
+ <rn-card
343
+ v-for="item in items"
344
+ :key="item.id"
345
+ :title="item.title"
346
+ elevation
347
+ >
348
+ <rn-text size="sm" :style="{ whiteSpace: 'pre-line' }">
349
+ {{ item.content }}
350
+ </rn-text>
351
+ </rn-card>
352
+ </rn-grid>
353
+ </rn-stack>
354
+ </div>
355
+ `,
356
+ }),
357
+ }
@@ -0,0 +1,52 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import Hero, { HeroProps } from '@/components/features/Hero.vue'
3
+
4
+ const meta: Meta<typeof Hero> = {
5
+ title: 'Features/Hero',
6
+ component: Hero,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ imageUrl: {
10
+ control: 'text',
11
+ },
12
+ linkUrl: {
13
+ control: 'text',
14
+ },
15
+ },
16
+ args: {
17
+ imageUrl:
18
+ 'https://reni-ec-pro.s3-ap-northeast-1.amazonaws.com/banner/63/d1270251298665d51cf9f298a3343257dd4559e4_sp.jpg',
19
+ linkUrl: 'https://official-goods-store.jp/naoto/',
20
+ },
21
+ }
22
+
23
+ export default meta
24
+ type StoryArgs = HeroProps & { slotText: string }
25
+ type Story = StoryObj<StoryArgs>
26
+ type OverridesStory = Omit<Story, 'argTypes'> & {
27
+ argTypes?: Record<string, any>
28
+ }
29
+
30
+ export const 基本: OverridesStory = {
31
+ args: {
32
+ slotText: '',
33
+ },
34
+ argTypes: {
35
+ default: { table: { disable: true } },
36
+ },
37
+ render: (args: StoryArgs) => ({
38
+ components: { 'rn-text': Text, 'rn-hero': Hero },
39
+ setup() {
40
+ return { args }
41
+ },
42
+ template: /* html */ `
43
+ <div>
44
+ <rn-hero
45
+ :image-url="args.imageUrl"
46
+ :link-url="args.linkUrl">
47
+ {{ args.slotText }}
48
+ </rn-hero>
49
+ </div>
50
+ `,
51
+ }),
52
+ }
@@ -0,0 +1,178 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+
3
+ import Html from '@/components/elements/Html.vue'
4
+
5
+ const meta = {
6
+ title: 'Elements/Html',
7
+ component: Html,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ nl2br: {
14
+ control: { type: 'boolean' },
15
+ },
16
+ removeEmpty: {
17
+ control: { type: 'boolean' },
18
+ },
19
+ forbiddenTags: {
20
+ control: { type: 'object' },
21
+ description: '禁止するHTMLタグの配列',
22
+ },
23
+ allowedAttributes: {
24
+ control: { type: 'object' },
25
+ description: '許可する属性の配列',
26
+ },
27
+ },
28
+ } satisfies Meta<typeof Html>
29
+
30
+ export default meta
31
+ type Story = StoryObj<typeof meta>
32
+
33
+ export const Default: Story = {
34
+ args: {
35
+ content: '<p>これは<strong>安全なHTML</strong>コンテンツです。</p>',
36
+ nl2br: false,
37
+ },
38
+ }
39
+
40
+ export const WithNewlines: Story = {
41
+ args: {
42
+ content: 'これは改行のある\nテキストです。\n\nもう一つの段落です。',
43
+ nl2br: true,
44
+ },
45
+ }
46
+
47
+ export const WithHtmlTags: Story = {
48
+ args: {
49
+ content: `
50
+ <p>これは<strong>強調された</strong>テキストです。</p>
51
+ <p><em>斜体</em>のテキストもあります。</p>
52
+ <ul>
53
+ <li>リストアイテム1</li>
54
+ <li>リストアイテム2</li>
55
+ <li>リストアイテム3</li>
56
+ </ul>
57
+ <p><a href="https://example.com">リンク</a>も含まれています。</p>
58
+ <blockquote>引用文も表示されます</blockquote>
59
+ <h2>見出しも使用可能</h2>
60
+ <table>
61
+ <thead>
62
+ <tr>
63
+ <th>ヘッダー1</th>
64
+ <th>ヘッダー2</th>
65
+ </tr>
66
+ </thead>
67
+ <tbody>
68
+ <tr>
69
+ <td>データ1</td>
70
+ <td>データ2</td>
71
+ </tr>
72
+ </tbody>
73
+ </table>
74
+ `,
75
+ nl2br: false,
76
+ },
77
+ }
78
+
79
+ export const UnsafeContent: Story = {
80
+ args: {
81
+ content: `
82
+ <p>これは安全なコンテンツです。</p>
83
+ <script>alert('この危険なスクリプトは削除されます')</script>
84
+ <p onclick="alert('これも削除されます')">クリックイベントは削除されます</p>
85
+ <img src="x" onerror="alert('onエラーイベントも削除')" />
86
+ <object>このobjectタグも削除されます</object>
87
+ <form><input type="text" />フォーム要素も削除されます</form>
88
+ `,
89
+ nl2br: false,
90
+ },
91
+ }
92
+
93
+ export const HtmlEntityDecoding: Story = {
94
+ args: {
95
+ content:
96
+ '&lt;p&gt;HTMLエンティティは&amp;nbsp;正しく&amp;lt;デコード&amp;gt;されます&lt;/p&gt;',
97
+ nl2br: false,
98
+ },
99
+ }
100
+
101
+ export const MixedContentWithNewlines: Story = {
102
+ args: {
103
+ content: `これは<strong>HTMLタグ</strong>と
104
+ 改行が
105
+ 混在した
106
+ コンテンツです。
107
+
108
+ <p>段落タグもあります。</p>`,
109
+ nl2br: true,
110
+ },
111
+ }
112
+
113
+ export const CustomForbiddenTags: Story = {
114
+ args: {
115
+ content: `
116
+ <p>通常は許可されるタグです</p>
117
+ <div>divタグは禁止されているので削除されます</div>
118
+ <span>spanタグも禁止されているので削除されます</span>
119
+ <strong>strongタグは許可されています</strong>
120
+ <em>emタグも許可されています</em>
121
+ <ul>
122
+ <li>リストも許可されています</li>
123
+ </ul>
124
+ `,
125
+ forbiddenTags: ['div', 'span'],
126
+ nl2br: false,
127
+ },
128
+ }
129
+
130
+ export const StrictMode: Story = {
131
+ args: {
132
+ content: `
133
+ <p>基本的なテキストのみ許可</p>
134
+ <strong>強調も削除されます</strong>
135
+ <em>斜体も削除されます</em>
136
+ <a href="https://example.com">リンクも削除されます</a>
137
+ <ul><li>リストも削除されます</li></ul>
138
+ <img src="image.jpg" alt="画像も削除されます" />
139
+ `,
140
+ forbiddenTags: [
141
+ 'strong',
142
+ 'em',
143
+ 'a',
144
+ 'ul',
145
+ 'ol',
146
+ 'li',
147
+ 'img',
148
+ 'table',
149
+ 'thead',
150
+ 'tbody',
151
+ 'tr',
152
+ 'td',
153
+ 'th',
154
+ ],
155
+ nl2br: false,
156
+ },
157
+ }
158
+
159
+ export const WithCustomAttributes: Story = {
160
+ args: {
161
+ content: `
162
+ <p class="custom-class" style="color: blue;">クラスとスタイルは許可されます</p>
163
+ <a href="https://example.com" target="_blank" title="リンクタイトル">属性付きリンク</a>
164
+ <img src="image.jpg" alt="画像" title="画像タイトル" width="100" />
165
+ <p data-custom="この属性は削除されます" onclick="alert('削除されます')">カスタム属性とイベントハンドラー</p>
166
+ `,
167
+ allowedAttributes: [
168
+ 'href',
169
+ 'style',
170
+ 'target',
171
+ 'class',
172
+ 'src',
173
+ 'alt',
174
+ 'title',
175
+ ],
176
+ nl2br: false,
177
+ },
178
+ }