@kkcompany/app-ui 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1,7 +1,43 @@
1
- # KKS React UI Components
1
+ # KKS UI Components(React)
2
2
 
3
3
  This is a repo for web react UI components, to be reused in projects.
4
4
 
5
+ ## Installation
6
+
7
+ ```sh
8
+ yarn add @kkcompany/app-ui
9
+ ```
10
+
11
+ or
12
+
13
+ ```sh
14
+ npm i @kkcompany/app-ui
15
+ ```
16
+
17
+
18
+ ## Examples
19
+
20
+ ```tsx
21
+ import { VideoItem } from '@kkcompany/app-ui'
22
+
23
+ const Template = (props) => (
24
+ <VideoItem
25
+ title="Sample Video"
26
+ href="https://example.com/play-page"
27
+ style={style={{
28
+ 'img': {
29
+ 'aspect-ratio': '1 / 1',
30
+ },
31
+ 'img + div': {
32
+ '--tag-background': 'hotpink',
33
+ }
34
+ }}}
35
+ imageUrl="https://example.com/thumbnail.jpg"
36
+ />
37
+ )
38
+ ```
39
+
40
+
5
41
  ## Sample Page
6
42
 
7
43
  **Local Development**
@@ -25,14 +61,4 @@ Sample sites are deployed to vercel for each git tag.
25
61
  yarn build
26
62
  ```
27
63
 
28
- ## Examples
29
-
30
- ```tsx
31
- import { Lovo } from '@kkcompany/ui'
32
64
 
33
- const template = (props) => (
34
- <Lovo showCount="5">
35
- <!-- children list -->
36
- </Lovo>
37
- )
38
- ```
package/dist/index.cjs CHANGED
@@ -1,5 +1,109 @@
1
1
  let __emotion_react_jsx_runtime = require("@emotion/react/jsx-runtime");
2
+ let react = require("react");
2
3
 
4
+ //#region src/Icon.tsx
5
+ /** @jsxImportSource @emotion/react */
6
+ const iconStyle = {
7
+ display: "inline-block",
8
+ width: "1em",
9
+ height: "0.8em",
10
+ backgroundColor: "currentColor",
11
+ maskPosition: "center",
12
+ maskSize: "cover",
13
+ maskRepeat: "no-repeat",
14
+ pointerEvents: "none",
15
+ touchAction: "none"
16
+ };
17
+ const Icon = ({ style = {}, src }) => /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("span", { css: [
18
+ iconStyle,
19
+ { maskImage: `url(data:image/svg+xml;base64,${src})` },
20
+ style
21
+ ] });
22
+ var Icon_default = Icon;
23
+
24
+ //#endregion
25
+ //#region src/icons/see-more.svg
26
+ var see_more_default = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSI4IiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTQgOCI+CiAgPHBhdGggc3Ryb2tlPSIjY2NjIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNLjc1Ljc1IDYuNyA2LjY4cS4wNy4wNi4xNCAwbTAgMHEwIDAgMCAwWm0wIDBMMTIuNzUuNzUiLz4KPC9zdmc+";
27
+
28
+ //#endregion
29
+ //#region src/SeeMore.tsx
30
+ const containerStyle = {
31
+ maxHeight: "2.5em",
32
+ overflow: "hidden",
33
+ display: "-webkit-box",
34
+ WebkitBoxOrient: "vertical",
35
+ textOverflow: "ellipsis",
36
+ transition: "max-height 0.2s ease-out",
37
+ "+ button": {
38
+ marginTop: "0.75em",
39
+ padding: "0",
40
+ fontSize: "inherit",
41
+ fontWeight: "bold",
42
+ background: "none",
43
+ border: "none",
44
+ "&:disabled": { opacity: "0" },
45
+ "> span": {
46
+ marginLeft: "2px",
47
+ padding: "1px",
48
+ fontSize: "0.75em",
49
+ transition: "transform 0.2s ease-out",
50
+ transformOrigin: "center"
51
+ }
52
+ }
53
+ };
54
+ const addonStyles = {
55
+ "no-expand": { WebkitLineClamp: "var(--see-more-collapsed-lines, 2)" },
56
+ collapsed: { WebkitLineClamp: "var(--see-more-collapsed-lines, 2)" },
57
+ expanded: {
58
+ maxHeight: "var(--see-more-max-height, 15em)",
59
+ "+ button > span": { transform: "rotateX(180deg)" }
60
+ }
61
+ };
62
+ const onResize = (container, handler) => {
63
+ const observer = new ResizeObserver(handler);
64
+ observer.observe(container);
65
+ return () => observer.disconnect();
66
+ };
67
+ const defaultMessages = {
68
+ seeMore: "もっと見る",
69
+ seeLess: "閉じる"
70
+ };
71
+ const SeeMore = ({ style, messages = defaultMessages, children, ...rest }) => {
72
+ const [status, setStatus] = (0, react.useState)("no-expand");
73
+ const [expandedHeight, setExpandedHeight] = (0, react.useState)();
74
+ const containeRef = (0, react.useRef)();
75
+ (0, react.useEffect)(() => {
76
+ if (!containeRef.current) return;
77
+ return onResize(containeRef.current, () => {
78
+ const scrollable = containeRef.current?.scrollHeight > 36;
79
+ setStatus((current) => current === "no-expand" && scrollable ? "collapsed" : current !== "no-expand" && !scrollable ? "no-expand" : current);
80
+ setExpandedHeight(containeRef.current?.scrollHeight);
81
+ });
82
+ }, []);
83
+ const toggle = () => setStatus((current) => current === "collapsed" ? "expanded" : "collapsing");
84
+ return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)("div", {
85
+ ...rest,
86
+ children: [/* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("div", {
87
+ css: [
88
+ expandedHeight && { "--see-more-max-height": `${expandedHeight}px` },
89
+ containerStyle,
90
+ addonStyles[status],
91
+ style
92
+ ],
93
+ ref: containeRef,
94
+ onTransitionEnd: () => setStatus((current) => current === "collapsing" ? "collapsed" : current),
95
+ children
96
+ }), /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)("button", {
97
+ type: "button",
98
+ disabled: status === "no-expand",
99
+ onClick: toggle,
100
+ children: [status === "collapsed" ? messages.seeMore : messages.seeLess, /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)(Icon_default, { src: see_more_default })]
101
+ })]
102
+ });
103
+ };
104
+ var SeeMore_default = SeeMore;
105
+
106
+ //#endregion
3
107
  //#region src/VideoThumbnail.tsx
4
108
  const videoThumbnailStyles = {
5
109
  position: "relative",
@@ -116,18 +220,9 @@ var VideoThumbnail_default = VideoThumbnail;
116
220
  const videoItemStyle = {
117
221
  padding: "0.75em 4%",
118
222
  display: "block",
119
- a: {
120
- color: "#ccc",
121
- textDecoration: "none"
122
- },
123
- "@media (max-width: 600px)": {
124
- "--description-display": "block",
125
- "--desktop-description-display": "none"
126
- },
127
- "@media (min-width: 601px)": {
128
- "--description-display": "none",
129
- "--desktop-description-display": "block"
130
- }
223
+ a: { textDecoration: "none" },
224
+ "@media (max-width: 600px)": { "--desktop-description-display": "none" },
225
+ "@media (min-width: 601px)": { "--description-display": "none" }
131
226
  };
132
227
  const infoStyle = {
133
228
  marginBottom: "0.5em",
@@ -142,19 +237,18 @@ const infoStyle = {
142
237
  }
143
238
  };
144
239
  const descriptionStyle = {
145
- display: "var(--description-display)",
240
+ display: "var(--description-display, -webkit-box)",
146
241
  overflow: "hidden",
242
+ WebkitBoxOrient: "vertical",
147
243
  WebkitLineClamp: 2,
244
+ color: "#ccc",
148
245
  textOverflow: "ellipsis",
149
246
  fontSize: "14px"
150
247
  };
151
248
  const desktopDescriptionStyle = {
152
- display: "var(--desktop-description-display)",
249
+ display: "var(--desktop-description-display, -webkit-box)",
153
250
  margin: "0.5em 0",
154
- overflow: "hidden",
155
- WebkitLineClamp: 3,
156
- textOverflow: "ellipsis",
157
- fontSize: "14px"
251
+ WebkitLineClamp: 3
158
252
  };
159
253
  const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data = {}, topTags = [], bottomTags = [], slots = { Link: "a" }, onClickThumbnail }) => /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)("div", {
160
254
  css: [videoItemStyle, style],
@@ -170,7 +264,7 @@ const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data
170
264
  }), /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)(slots.Link, {
171
265
  href,
172
266
  children: [data.title || data.display_text, /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("div", {
173
- css: desktopDescriptionStyle,
267
+ css: [descriptionStyle, desktopDescriptionStyle],
174
268
  children: data.synopsis
175
269
  })]
176
270
  })]
@@ -182,5 +276,7 @@ const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data
182
276
  var VideoItem_default = VideoItem;
183
277
 
184
278
  //#endregion
279
+ exports.Icon = Icon_default;
280
+ exports.SeeMore = SeeMore_default;
185
281
  exports.VideoItem = VideoItem_default;
186
282
  exports.VideoThumbnail = VideoThumbnail_default;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,33 @@
1
+ import * as _emotion_react_jsx_runtime0 from "@emotion/react/jsx-runtime";
1
2
  import { CSSObject } from "@emotion/react";
2
- import Link from "next/link";
3
3
  import { ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
4
- import * as _emotion_react_jsx_runtime0 from "@emotion/react/jsx-runtime";
4
+ import Link from "next/link";
5
5
 
6
+ //#region src/Icon.d.ts
7
+ declare const Icon: ({
8
+ style,
9
+ src
10
+ }: {
11
+ style?: {};
12
+ src: any;
13
+ }) => _emotion_react_jsx_runtime0.JSX.Element;
14
+ //#endregion
15
+ //#region src/SeeMore.d.ts
16
+ declare const defaultMessages: {
17
+ seeMore: string;
18
+ seeLess: string;
19
+ };
20
+ declare const SeeMore: ({
21
+ style,
22
+ messages,
23
+ children,
24
+ ...rest
25
+ }: {
26
+ style?: CSSObject;
27
+ messages?: typeof defaultMessages;
28
+ children?: ReactNode;
29
+ }) => _emotion_react_jsx_runtime0.JSX.Element;
30
+ //#endregion
6
31
  //#region src/VideoItem.d.ts
7
32
  type VideoDetail = {
8
33
  title?: string;
@@ -59,4 +84,4 @@ declare const VideoThumbnail: ({
59
84
  onClick?: MouseEventHandler<HTMLAnchorElement>;
60
85
  }) => _emotion_react_jsx_runtime0.JSX.Element;
61
86
  //#endregion
62
- export { VideoItem, VideoThumbnail };
87
+ export { Icon, SeeMore, VideoItem, VideoThumbnail };
package/dist/index.d.mts CHANGED
@@ -1,8 +1,33 @@
1
1
  import * as _emotion_react_jsx_runtime0 from "@emotion/react/jsx-runtime";
2
+ import { ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
2
3
  import { CSSObject } from "@emotion/react";
3
4
  import Link from "next/link";
4
- import { ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
5
5
 
6
+ //#region src/Icon.d.ts
7
+ declare const Icon: ({
8
+ style,
9
+ src
10
+ }: {
11
+ style?: {};
12
+ src: any;
13
+ }) => _emotion_react_jsx_runtime0.JSX.Element;
14
+ //#endregion
15
+ //#region src/SeeMore.d.ts
16
+ declare const defaultMessages: {
17
+ seeMore: string;
18
+ seeLess: string;
19
+ };
20
+ declare const SeeMore: ({
21
+ style,
22
+ messages,
23
+ children,
24
+ ...rest
25
+ }: {
26
+ style?: CSSObject;
27
+ messages?: typeof defaultMessages;
28
+ children?: ReactNode;
29
+ }) => _emotion_react_jsx_runtime0.JSX.Element;
30
+ //#endregion
6
31
  //#region src/VideoItem.d.ts
7
32
  type VideoDetail = {
8
33
  title?: string;
@@ -59,4 +84,4 @@ declare const VideoThumbnail: ({
59
84
  onClick?: MouseEventHandler<HTMLAnchorElement>;
60
85
  }) => _emotion_react_jsx_runtime0.JSX.Element;
61
86
  //#endregion
62
- export { VideoItem, VideoThumbnail };
87
+ export { Icon, SeeMore, VideoItem, VideoThumbnail };
package/dist/index.mjs CHANGED
@@ -1,5 +1,109 @@
1
1
  import { jsx, jsxs } from "@emotion/react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
2
3
 
4
+ //#region src/Icon.tsx
5
+ /** @jsxImportSource @emotion/react */
6
+ const iconStyle = {
7
+ display: "inline-block",
8
+ width: "1em",
9
+ height: "0.8em",
10
+ backgroundColor: "currentColor",
11
+ maskPosition: "center",
12
+ maskSize: "cover",
13
+ maskRepeat: "no-repeat",
14
+ pointerEvents: "none",
15
+ touchAction: "none"
16
+ };
17
+ const Icon = ({ style = {}, src }) => /* @__PURE__ */ jsx("span", { css: [
18
+ iconStyle,
19
+ { maskImage: `url(data:image/svg+xml;base64,${src})` },
20
+ style
21
+ ] });
22
+ var Icon_default = Icon;
23
+
24
+ //#endregion
25
+ //#region src/icons/see-more.svg
26
+ var see_more_default = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSI4IiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTQgOCI+CiAgPHBhdGggc3Ryb2tlPSIjY2NjIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNLjc1Ljc1IDYuNyA2LjY4cS4wNy4wNi4xNCAwbTAgMHEwIDAgMCAwWm0wIDBMMTIuNzUuNzUiLz4KPC9zdmc+";
27
+
28
+ //#endregion
29
+ //#region src/SeeMore.tsx
30
+ const containerStyle = {
31
+ maxHeight: "2.5em",
32
+ overflow: "hidden",
33
+ display: "-webkit-box",
34
+ WebkitBoxOrient: "vertical",
35
+ textOverflow: "ellipsis",
36
+ transition: "max-height 0.2s ease-out",
37
+ "+ button": {
38
+ marginTop: "0.75em",
39
+ padding: "0",
40
+ fontSize: "inherit",
41
+ fontWeight: "bold",
42
+ background: "none",
43
+ border: "none",
44
+ "&:disabled": { opacity: "0" },
45
+ "> span": {
46
+ marginLeft: "2px",
47
+ padding: "1px",
48
+ fontSize: "0.75em",
49
+ transition: "transform 0.2s ease-out",
50
+ transformOrigin: "center"
51
+ }
52
+ }
53
+ };
54
+ const addonStyles = {
55
+ "no-expand": { WebkitLineClamp: "var(--see-more-collapsed-lines, 2)" },
56
+ collapsed: { WebkitLineClamp: "var(--see-more-collapsed-lines, 2)" },
57
+ expanded: {
58
+ maxHeight: "var(--see-more-max-height, 15em)",
59
+ "+ button > span": { transform: "rotateX(180deg)" }
60
+ }
61
+ };
62
+ const onResize = (container, handler) => {
63
+ const observer = new ResizeObserver(handler);
64
+ observer.observe(container);
65
+ return () => observer.disconnect();
66
+ };
67
+ const defaultMessages = {
68
+ seeMore: "もっと見る",
69
+ seeLess: "閉じる"
70
+ };
71
+ const SeeMore = ({ style, messages = defaultMessages, children, ...rest }) => {
72
+ const [status, setStatus] = useState("no-expand");
73
+ const [expandedHeight, setExpandedHeight] = useState();
74
+ const containeRef = useRef();
75
+ useEffect(() => {
76
+ if (!containeRef.current) return;
77
+ return onResize(containeRef.current, () => {
78
+ const scrollable = containeRef.current?.scrollHeight > 36;
79
+ setStatus((current) => current === "no-expand" && scrollable ? "collapsed" : current !== "no-expand" && !scrollable ? "no-expand" : current);
80
+ setExpandedHeight(containeRef.current?.scrollHeight);
81
+ });
82
+ }, []);
83
+ const toggle = () => setStatus((current) => current === "collapsed" ? "expanded" : "collapsing");
84
+ return /* @__PURE__ */ jsxs("div", {
85
+ ...rest,
86
+ children: [/* @__PURE__ */ jsx("div", {
87
+ css: [
88
+ expandedHeight && { "--see-more-max-height": `${expandedHeight}px` },
89
+ containerStyle,
90
+ addonStyles[status],
91
+ style
92
+ ],
93
+ ref: containeRef,
94
+ onTransitionEnd: () => setStatus((current) => current === "collapsing" ? "collapsed" : current),
95
+ children
96
+ }), /* @__PURE__ */ jsxs("button", {
97
+ type: "button",
98
+ disabled: status === "no-expand",
99
+ onClick: toggle,
100
+ children: [status === "collapsed" ? messages.seeMore : messages.seeLess, /* @__PURE__ */ jsx(Icon_default, { src: see_more_default })]
101
+ })]
102
+ });
103
+ };
104
+ var SeeMore_default = SeeMore;
105
+
106
+ //#endregion
3
107
  //#region src/VideoThumbnail.tsx
4
108
  const videoThumbnailStyles = {
5
109
  position: "relative",
@@ -116,18 +220,9 @@ var VideoThumbnail_default = VideoThumbnail;
116
220
  const videoItemStyle = {
117
221
  padding: "0.75em 4%",
118
222
  display: "block",
119
- a: {
120
- color: "#ccc",
121
- textDecoration: "none"
122
- },
123
- "@media (max-width: 600px)": {
124
- "--description-display": "block",
125
- "--desktop-description-display": "none"
126
- },
127
- "@media (min-width: 601px)": {
128
- "--description-display": "none",
129
- "--desktop-description-display": "block"
130
- }
223
+ a: { textDecoration: "none" },
224
+ "@media (max-width: 600px)": { "--desktop-description-display": "none" },
225
+ "@media (min-width: 601px)": { "--description-display": "none" }
131
226
  };
132
227
  const infoStyle = {
133
228
  marginBottom: "0.5em",
@@ -142,19 +237,18 @@ const infoStyle = {
142
237
  }
143
238
  };
144
239
  const descriptionStyle = {
145
- display: "var(--description-display)",
240
+ display: "var(--description-display, -webkit-box)",
146
241
  overflow: "hidden",
242
+ WebkitBoxOrient: "vertical",
147
243
  WebkitLineClamp: 2,
244
+ color: "#ccc",
148
245
  textOverflow: "ellipsis",
149
246
  fontSize: "14px"
150
247
  };
151
248
  const desktopDescriptionStyle = {
152
- display: "var(--desktop-description-display)",
249
+ display: "var(--desktop-description-display, -webkit-box)",
153
250
  margin: "0.5em 0",
154
- overflow: "hidden",
155
- WebkitLineClamp: 3,
156
- textOverflow: "ellipsis",
157
- fontSize: "14px"
251
+ WebkitLineClamp: 3
158
252
  };
159
253
  const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data = {}, topTags = [], bottomTags = [], slots = { Link: "a" }, onClickThumbnail }) => /* @__PURE__ */ jsxs("div", {
160
254
  css: [videoItemStyle, style],
@@ -170,7 +264,7 @@ const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data
170
264
  }), /* @__PURE__ */ jsxs(slots.Link, {
171
265
  href,
172
266
  children: [data.title || data.display_text, /* @__PURE__ */ jsx("div", {
173
- css: desktopDescriptionStyle,
267
+ css: [descriptionStyle, desktopDescriptionStyle],
174
268
  children: data.synopsis
175
269
  })]
176
270
  })]
@@ -182,4 +276,4 @@ const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data
182
276
  var VideoItem_default = VideoItem;
183
277
 
184
278
  //#endregion
185
- export { VideoItem_default as VideoItem, VideoThumbnail_default as VideoThumbnail };
279
+ export { Icon_default as Icon, SeeMore_default as SeeMore, VideoItem_default as VideoItem, VideoThumbnail_default as VideoThumbnail };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kkcompany/app-ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "module": "dist/index.mjs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.mts",
@@ -13,7 +13,7 @@
13
13
  "import": "./dist/index.mjs",
14
14
  "module": "./dist/index.mjs",
15
15
  "types": "./dist/index.d.mts",
16
- "require": "./dist/index.cjs"
16
+ "require": "./dist/index.cjs"
17
17
  }
18
18
  },
19
19
  "license": "MIT",
@@ -24,9 +24,15 @@
24
24
  "dependencies": {
25
25
  "@emotion/react": "^11.14.0"
26
26
  },
27
+ "peerDependencies": {
28
+ "react": "^16.8.0",
29
+ "react-dom": "^16.8.0"
30
+ },
27
31
  "devDependencies": {
28
32
  "@biomejs/biome": "^2.3.5",
33
+ "binary-base64-loader": "^1.0.0",
29
34
  "next": "^16.0.2",
35
+ "rollup-plugin-base64": "^1.0.1",
30
36
  "tsdown": "^0.16.4",
31
37
  "typescript": "^5.9.3"
32
38
  }