line-flex-message-renderer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kanketsu-jp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # line-flex-message-renderer
2
+
3
+ React component to render LINE Flex Message JSON as a visual preview — pixel-accurate to the LINE app.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install line-flex-message-renderer
9
+ # or
10
+ pnpm add line-flex-message-renderer
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```tsx
16
+ import { FlexMessagePreview, LineChatFrame } from 'line-flex-message-renderer';
17
+
18
+ const flexJson = {
19
+ type: 'bubble',
20
+ body: {
21
+ type: 'box',
22
+ layout: 'vertical',
23
+ contents: [
24
+ { type: 'text', text: 'Hello, World!', weight: 'bold', size: 'xl' },
25
+ ],
26
+ },
27
+ };
28
+
29
+ function App() {
30
+ return (
31
+ <LineChatFrame>
32
+ <FlexMessagePreview json={flexJson} />
33
+ </LineChatFrame>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## Components
39
+
40
+ ### FlexMessagePreview
41
+
42
+ Renders a Flex Message bubble or carousel.
43
+
44
+ ```tsx
45
+ <FlexMessagePreview json={flexBubbleOrCarousel} className="my-class" style={{ margin: 8 }} />
46
+ ```
47
+
48
+ | Prop | Type | Description |
49
+ |------|------|-------------|
50
+ | `json` | `FlexContainer` | Flex Message JSON (bubble or carousel) |
51
+ | `className` | `string?` | Additional CSS class |
52
+ | `style` | `CSSProperties?` | Additional inline styles |
53
+
54
+ ### LineChatFrame
55
+
56
+ Wraps content in a LINE chat UI frame.
57
+
58
+ ```tsx
59
+ <LineChatFrame accountName="My Bot" width={375}>
60
+ <FlexMessagePreview json={flexJson} />
61
+ </LineChatFrame>
62
+ ```
63
+
64
+ | Prop | Type | Default | Description |
65
+ |------|------|---------|-------------|
66
+ | `children` | `ReactNode` | — | Content to display |
67
+ | `accountName` | `string?` | `"トーク"` | Header title |
68
+ | `avatarUrl` | `string?` | — | Avatar image URL (defaults to green BOT icon) |
69
+ | `width` | `number?` | `375` | Frame width in pixels |
70
+
71
+ ### LineTextBubble
72
+
73
+ Renders a plain text message bubble.
74
+
75
+ ```tsx
76
+ <LineTextBubble text="Hello!" />
77
+ ```
78
+
79
+ ## Supported Flex Message Components
80
+
81
+ - **box** — vertical / horizontal / baseline layouts
82
+ - **text** — with span support, wrapping, max lines
83
+ - **image** — aspect ratio, aspect mode (cover/fit)
84
+ - **button** — primary / secondary / link styles
85
+ - **separator** — horizontal line
86
+ - **spacer** — flexible space
87
+ - **filler** — flex-grow space
88
+ - **icon** — inline icon image
89
+
90
+ ## Bubble Sizes
91
+
92
+ | Size | Width |
93
+ |------|-------|
94
+ | nano | 120px |
95
+ | micro | 150px |
96
+ | kilo | 230px |
97
+ | mega (default) | 300px |
98
+ | giga | 386px |
99
+
100
+ ## Carousel Support
101
+
102
+ Pass a carousel container to render multiple bubbles with horizontal scrolling:
103
+
104
+ ```tsx
105
+ <FlexMessagePreview
106
+ json={{
107
+ type: 'carousel',
108
+ contents: [bubble1, bubble2, bubble3],
109
+ }}
110
+ />
111
+ ```
112
+
113
+ ## Development
114
+
115
+ ```bash
116
+ pnpm install
117
+ pnpm storybook # Start Storybook dev server
118
+ pnpm test # Run tests
119
+ pnpm build # Build for production
120
+ pnpm typecheck # Type check
121
+ pnpm lint # Lint
122
+ ```
123
+
124
+ ## License
125
+
126
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,472 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+
5
+ // src/constants.ts
6
+ var TEXT_SIZE = {
7
+ xxs: "11px",
8
+ xs: "12px",
9
+ sm: "13px",
10
+ md: "14px",
11
+ lg: "16px",
12
+ xl: "18px",
13
+ xxl: "22px",
14
+ "3xl": "26px",
15
+ "4xl": "30px",
16
+ "5xl": "36px"
17
+ };
18
+ var SPACING = {
19
+ none: "0px",
20
+ xs: "2px",
21
+ sm: "4px",
22
+ md: "8px",
23
+ lg: "12px",
24
+ xl: "16px",
25
+ xxl: "20px"
26
+ };
27
+ var IMAGE_SIZE = {
28
+ xxs: "40px",
29
+ xs: "60px",
30
+ sm: "80px",
31
+ md: "100px",
32
+ lg: "120px",
33
+ xl: "150px",
34
+ xxl: "180px",
35
+ "3xl": "220px",
36
+ "4xl": "260px",
37
+ "5xl": "300px",
38
+ full: "100%"
39
+ };
40
+ var ICON_SIZE = {
41
+ xxs: "14px",
42
+ xs: "16px",
43
+ sm: "18px",
44
+ md: "20px",
45
+ lg: "24px",
46
+ xl: "28px",
47
+ xxl: "32px"
48
+ };
49
+ var BUBBLE_WIDTH = {
50
+ nano: "120px",
51
+ micro: "150px",
52
+ kilo: "230px",
53
+ mega: "300px",
54
+ giga: "386px"
55
+ };
56
+
57
+ // src/utils.ts
58
+ function resolveSize(value, map, fallback) {
59
+ if (!value) return fallback;
60
+ return map[value] ?? value;
61
+ }
62
+ function FlexButtonComponent({ component }) {
63
+ const isPrimary = component.style === "primary";
64
+ const isLink = component.style === "link";
65
+ const height = component.height === "sm" ? "40px" : "52px";
66
+ const style = {
67
+ width: "100%",
68
+ height,
69
+ display: "flex",
70
+ alignItems: "center",
71
+ justifyContent: "center",
72
+ borderRadius: isPrimary || component.style === "secondary" ? "9999px" : void 0,
73
+ backgroundColor: isPrimary ? component.color ?? "#17C950" : isLink ? "transparent" : "#EFEFEF",
74
+ color: isPrimary ? "#ffffff" : isLink ? component.color ?? "#42659A" : "#111111",
75
+ fontSize: TEXT_SIZE.sm,
76
+ fontWeight: 600,
77
+ border: "none",
78
+ cursor: "pointer",
79
+ marginTop: resolveSize(component.margin, SPACING, void 0),
80
+ flex: component.flex !== void 0 ? `${component.flex} 0 0%` : void 0
81
+ };
82
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style, children: component.action.label });
83
+ }
84
+ function FlexIconComponent({ component }) {
85
+ const size = resolveSize(component.size, ICON_SIZE, ICON_SIZE.md);
86
+ return /* @__PURE__ */ jsxRuntime.jsx(
87
+ "img",
88
+ {
89
+ src: component.url,
90
+ alt: "",
91
+ style: { width: size, height: size, objectFit: "contain" }
92
+ }
93
+ );
94
+ }
95
+ function FlexImageComponent({ component }) {
96
+ const [w, h] = (component.aspectRatio ?? "1:1").split(":").map(Number);
97
+ const style = {
98
+ width: component.size === "full" ? "100%" : resolveSize(component.size, IMAGE_SIZE, IMAGE_SIZE.md),
99
+ marginTop: resolveSize(component.margin, SPACING, void 0),
100
+ flex: component.flex !== void 0 ? `${component.flex} 0 0%` : void 0,
101
+ backgroundColor: component.backgroundColor
102
+ };
103
+ const innerStyle = {
104
+ width: "100%",
105
+ paddingTop: `${h / w * 100}%`,
106
+ position: "relative",
107
+ overflow: "hidden"
108
+ };
109
+ const imgStyle = {
110
+ position: "absolute",
111
+ top: 0,
112
+ left: 0,
113
+ width: "100%",
114
+ height: "100%",
115
+ objectFit: component.aspectMode === "fit" ? "contain" : "cover"
116
+ };
117
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: innerStyle, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: component.url, alt: "", style: imgStyle }) }) });
118
+ }
119
+ function FlexSeparatorComponent({
120
+ component
121
+ }) {
122
+ const style = {
123
+ borderTop: `1px solid ${component.color ?? "#E5E5E5"}`,
124
+ marginTop: resolveSize(component.margin, SPACING, void 0),
125
+ width: "100%"
126
+ };
127
+ return /* @__PURE__ */ jsxRuntime.jsx("hr", { style });
128
+ }
129
+ function FlexSpanComponent({ span }) {
130
+ const style = {
131
+ fontSize: resolveSize(span.size, TEXT_SIZE, "inherit"),
132
+ color: span.color,
133
+ fontWeight: span.weight === "bold" ? 700 : void 0,
134
+ textDecoration: span.decoration !== "none" ? span.decoration : void 0,
135
+ fontStyle: span.style
136
+ };
137
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { style, children: span.text });
138
+ }
139
+ var alignMap = {
140
+ start: "left",
141
+ center: "center",
142
+ end: "right"
143
+ };
144
+ var gravityMap = {
145
+ top: "flex-start",
146
+ center: "center",
147
+ bottom: "flex-end"
148
+ };
149
+ function FlexTextComponent({ component }) {
150
+ const hasSpans = component.contents && component.contents.length > 0;
151
+ const fontSize = resolveSize(component.size, TEXT_SIZE, TEXT_SIZE.md);
152
+ const style = {
153
+ fontSize,
154
+ color: component.color,
155
+ fontWeight: component.weight === "bold" ? 700 : 400,
156
+ textAlign: alignMap[component.align ?? "start"] ?? "left",
157
+ marginTop: resolveSize(component.margin, SPACING, void 0),
158
+ flex: component.flex !== void 0 ? `${component.flex} 0 0%` : void 0,
159
+ alignSelf: component.gravity ? gravityMap[component.gravity] : void 0,
160
+ textDecoration: component.decoration !== "none" ? component.decoration : void 0,
161
+ fontStyle: component.style,
162
+ lineHeight: component.lineSpacing ?? 1.4,
163
+ ...!component.wrap ? {
164
+ overflow: "hidden",
165
+ textOverflow: "ellipsis",
166
+ whiteSpace: "nowrap"
167
+ } : {
168
+ whiteSpace: "pre-wrap",
169
+ wordBreak: "break-word"
170
+ },
171
+ ...component.maxLines && component.wrap ? {
172
+ display: "-webkit-box",
173
+ WebkitLineClamp: component.maxLines,
174
+ WebkitBoxOrient: "vertical",
175
+ overflow: "hidden"
176
+ } : {}
177
+ };
178
+ if (hasSpans) {
179
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { style, children: component.contents?.map((span, i) => /* @__PURE__ */ jsxRuntime.jsx(FlexSpanComponent, { span }, i)) });
180
+ }
181
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { style, children: component.text });
182
+ }
183
+ function FlexComponentRenderer({
184
+ component
185
+ }) {
186
+ switch (component.type) {
187
+ case "box":
188
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexBoxComponent, { component });
189
+ case "text":
190
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexTextComponent, { component });
191
+ case "image":
192
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexImageComponent, { component });
193
+ case "button":
194
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexButtonComponent, { component });
195
+ case "separator":
196
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexSeparatorComponent, { component });
197
+ case "spacer":
198
+ return /* @__PURE__ */ jsxRuntime.jsx(
199
+ "div",
200
+ {
201
+ style: {
202
+ flexGrow: 1,
203
+ height: resolveSize(component.size, SPACING, "0px")
204
+ }
205
+ }
206
+ );
207
+ case "filler":
208
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flexGrow: component.flex ?? 1 } });
209
+ case "icon":
210
+ return /* @__PURE__ */ jsxRuntime.jsx(FlexIconComponent, { component });
211
+ default:
212
+ return null;
213
+ }
214
+ }
215
+ function FlexBoxComponent({ component }) {
216
+ const isVertical = component.layout === "vertical";
217
+ const isBaseline = component.layout === "baseline";
218
+ const style = {
219
+ display: "flex",
220
+ flexDirection: isVertical ? "column" : "row",
221
+ alignItems: isBaseline ? "baseline" : component.alignItems ?? (isVertical ? "stretch" : "center"),
222
+ justifyContent: component.justifyContent,
223
+ gap: resolveSize(component.spacing, SPACING, void 0),
224
+ marginTop: resolveSize(component.margin, SPACING, void 0),
225
+ padding: resolveSize(component.paddingAll, SPACING, void 0),
226
+ paddingTop: resolveSize(component.paddingTop, SPACING, void 0),
227
+ paddingBottom: resolveSize(component.paddingBottom, SPACING, void 0),
228
+ paddingLeft: resolveSize(component.paddingStart, SPACING, void 0),
229
+ paddingRight: resolveSize(component.paddingEnd, SPACING, void 0),
230
+ backgroundColor: component.backgroundColor,
231
+ borderRadius: component.cornerRadius,
232
+ borderColor: component.borderColor,
233
+ borderWidth: component.borderWidth,
234
+ borderStyle: component.borderWidth ? "solid" : void 0,
235
+ flex: component.flex !== void 0 ? `${component.flex} 0 0%` : void 0
236
+ };
237
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children: component.contents.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(FlexComponentRenderer, { component: child }, i)) });
238
+ }
239
+ function BubbleRenderer({
240
+ json,
241
+ className,
242
+ style: extraStyle
243
+ }) {
244
+ const width = BUBBLE_WIDTH[json.size ?? "mega"];
245
+ const headerBg = json.styles?.header?.backgroundColor;
246
+ const bodyBg = json.styles?.body?.backgroundColor;
247
+ const footerBg = json.styles?.footer?.backgroundColor;
248
+ const footerSep = json.styles?.footer?.separator;
249
+ const bodySep = json.styles?.body?.separator;
250
+ const heroSep = json.styles?.hero?.separator;
251
+ return /* @__PURE__ */ jsxRuntime.jsxs(
252
+ "div",
253
+ {
254
+ className,
255
+ style: {
256
+ width,
257
+ maxWidth: "100%",
258
+ borderRadius: "16px",
259
+ overflow: "hidden",
260
+ backgroundColor: "#ffffff",
261
+ boxShadow: "0 1px 6px rgba(0,0,0,0.12)",
262
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", Arial, sans-serif',
263
+ ...extraStyle
264
+ },
265
+ children: [
266
+ json.header && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "16px 16px 0", backgroundColor: headerBg }, children: /* @__PURE__ */ jsxRuntime.jsx(FlexBoxComponent, { component: json.header }) }),
267
+ heroSep && /* @__PURE__ */ jsxRuntime.jsx("hr", { style: { borderTop: "1px solid #E5E5E5", margin: 0 } }),
268
+ json.hero && /* @__PURE__ */ jsxRuntime.jsx(FlexImageComponent, { component: json.hero }),
269
+ bodySep && /* @__PURE__ */ jsxRuntime.jsx("hr", { style: { borderTop: "1px solid #E5E5E5", margin: 0 } }),
270
+ json.body && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "16px", backgroundColor: bodyBg }, children: /* @__PURE__ */ jsxRuntime.jsx(FlexBoxComponent, { component: json.body }) }),
271
+ footerSep && /* @__PURE__ */ jsxRuntime.jsx("hr", { style: { borderTop: "1px solid #E5E5E5", margin: 0 } }),
272
+ json.footer && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "8px 16px 16px", backgroundColor: footerBg }, children: /* @__PURE__ */ jsxRuntime.jsx(FlexBoxComponent, { component: json.footer }) })
273
+ ]
274
+ }
275
+ );
276
+ }
277
+ function FlexMessagePreview({
278
+ json,
279
+ className,
280
+ style
281
+ }) {
282
+ if (json.type === "carousel") {
283
+ return /* @__PURE__ */ jsxRuntime.jsx(
284
+ "div",
285
+ {
286
+ className,
287
+ style: {
288
+ display: "flex",
289
+ gap: 8,
290
+ overflowX: "auto",
291
+ scrollSnapType: "x mandatory",
292
+ ...style
293
+ },
294
+ children: json.contents.map((bubble, i) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { scrollSnapAlign: "start", flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(BubbleRenderer, { json: bubble }) }, i))
295
+ }
296
+ );
297
+ }
298
+ return /* @__PURE__ */ jsxRuntime.jsx(BubbleRenderer, { json, className, style });
299
+ }
300
+ function DefaultAvatar() {
301
+ return /* @__PURE__ */ jsxRuntime.jsx(
302
+ "div",
303
+ {
304
+ style: {
305
+ width: 36,
306
+ height: 36,
307
+ borderRadius: "50%",
308
+ backgroundColor: "#00B900",
309
+ display: "flex",
310
+ alignItems: "center",
311
+ justifyContent: "center",
312
+ flexShrink: 0,
313
+ color: "#fff",
314
+ fontSize: 11,
315
+ fontWeight: 700
316
+ },
317
+ children: "BOT"
318
+ }
319
+ );
320
+ }
321
+ function LineChatFrame({
322
+ children,
323
+ accountName = "\u30C8\u30FC\u30AF",
324
+ avatarUrl,
325
+ width = 375
326
+ }) {
327
+ return /* @__PURE__ */ jsxRuntime.jsxs(
328
+ "div",
329
+ {
330
+ style: {
331
+ width,
332
+ minHeight: 500,
333
+ borderRadius: 12,
334
+ overflow: "hidden",
335
+ boxShadow: "0 4px 24px rgba(0,0,0,0.18)",
336
+ display: "flex",
337
+ flexDirection: "column",
338
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", Arial, sans-serif'
339
+ },
340
+ children: [
341
+ /* @__PURE__ */ jsxRuntime.jsxs(
342
+ "div",
343
+ {
344
+ style: {
345
+ backgroundColor: "#00B900",
346
+ color: "#fff",
347
+ padding: "12px 16px",
348
+ fontSize: 16,
349
+ fontWeight: 700,
350
+ display: "flex",
351
+ alignItems: "center",
352
+ gap: 8
353
+ },
354
+ children: [
355
+ /* @__PURE__ */ jsxRuntime.jsx(
356
+ "svg",
357
+ {
358
+ width: "18",
359
+ height: "18",
360
+ viewBox: "0 0 24 24",
361
+ fill: "none",
362
+ stroke: "currentColor",
363
+ strokeWidth: "2.5",
364
+ strokeLinecap: "round",
365
+ strokeLinejoin: "round",
366
+ role: "img",
367
+ "aria-label": "Back",
368
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6" })
369
+ }
370
+ ),
371
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: accountName })
372
+ ]
373
+ }
374
+ ),
375
+ /* @__PURE__ */ jsxRuntime.jsx(
376
+ "div",
377
+ {
378
+ style: {
379
+ backgroundColor: "#7B9EB0",
380
+ flex: 1,
381
+ padding: "16px 12px",
382
+ display: "flex",
383
+ flexDirection: "column",
384
+ gap: 8
385
+ },
386
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
387
+ "div",
388
+ {
389
+ style: {
390
+ display: "flex",
391
+ alignItems: "flex-end",
392
+ gap: 8
393
+ },
394
+ children: [
395
+ avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(
396
+ "img",
397
+ {
398
+ src: avatarUrl,
399
+ alt: "",
400
+ style: {
401
+ width: 36,
402
+ height: 36,
403
+ borderRadius: "50%",
404
+ objectFit: "cover",
405
+ flexShrink: 0
406
+ }
407
+ }
408
+ ) : /* @__PURE__ */ jsxRuntime.jsx(DefaultAvatar, {}),
409
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { maxWidth: "calc(100% - 52px)" }, children })
410
+ ]
411
+ }
412
+ )
413
+ }
414
+ ),
415
+ /* @__PURE__ */ jsxRuntime.jsx(
416
+ "div",
417
+ {
418
+ style: {
419
+ backgroundColor: "#F7F7F7",
420
+ padding: "10px 12px",
421
+ display: "flex",
422
+ alignItems: "center",
423
+ gap: 8,
424
+ borderTop: "1px solid #E0E0E0"
425
+ },
426
+ children: /* @__PURE__ */ jsxRuntime.jsx(
427
+ "div",
428
+ {
429
+ style: {
430
+ flex: 1,
431
+ backgroundColor: "#fff",
432
+ borderRadius: 20,
433
+ padding: "8px 14px",
434
+ fontSize: 14,
435
+ color: "#999"
436
+ },
437
+ children: "Aa"
438
+ }
439
+ )
440
+ }
441
+ )
442
+ ]
443
+ }
444
+ );
445
+ }
446
+ function LineTextBubble({ text }) {
447
+ return /* @__PURE__ */ jsxRuntime.jsx(
448
+ "div",
449
+ {
450
+ style: {
451
+ backgroundColor: "#ffffff",
452
+ borderRadius: "16px 16px 16px 4px",
453
+ padding: "10px 14px",
454
+ fontSize: 14,
455
+ lineHeight: 1.5,
456
+ color: "#111111",
457
+ whiteSpace: "pre-wrap",
458
+ wordBreak: "break-word",
459
+ maxWidth: 260,
460
+ boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
461
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", Arial, sans-serif'
462
+ },
463
+ children: text
464
+ }
465
+ );
466
+ }
467
+
468
+ exports.FlexMessagePreview = FlexMessagePreview;
469
+ exports.LineChatFrame = LineChatFrame;
470
+ exports.LineTextBubble = LineTextBubble;
471
+ //# sourceMappingURL=index.cjs.map
472
+ //# sourceMappingURL=index.cjs.map