hyperapp-is 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.
@@ -0,0 +1,193 @@
1
+ // hyperapp-ui / core / component.ts
2
+ import { h, text } from "hyperapp";
3
+ import { getValue, setValue } from "./state";
4
+ // ========== ========== ========== ========== ==========
5
+ // 補助関数
6
+ // ========== ========== ========== ========== ==========
7
+ // ---------- ---------- ---------- ---------- ----------
8
+ // el
9
+ // ---------- ---------- ---------- ---------- ----------
10
+ /**
11
+ * h 関数のラッパー
12
+ * 他でjsxを使用した場合、hが競合する可能性があるので作成した
13
+ *
14
+ * @template S
15
+ * @param {string} tag - タグ名
16
+ * @returns {(props:{ [key: string] any }, ...children:any[]) => VNode<S>}
17
+ */
18
+ export const el = (tag) => (props, ...children) => h(tag, props !== null && props !== void 0 ? props : {}, children
19
+ .flat()
20
+ .map((child) => typeof child === "object" ? child : text(child)));
21
+ /* element */
22
+ const button = el("button");
23
+ // ---------- ---------- ---------- ---------- ----------
24
+ // concatAction
25
+ // ---------- ---------- ---------- ---------- ----------
26
+ /**
27
+ * アクションを結合して結果を返す
28
+ *
29
+ * @template S
30
+ * @template E
31
+ * @param {undefined | (state: S, e: E) => S | [S, Effect<S>]} action - 結合するアクション
32
+ * @param {S} newState - 結合するステート
33
+ * @param {E} e - イベント (任意のイベント型)
34
+ * @returns {S | [S, Effect<S>]}
35
+ */
36
+ export const concatAction = function (action, newState, e) {
37
+ if (!action)
38
+ return newState;
39
+ const effect = (dispatch) => {
40
+ // 次の描画を待たないと、newStateと同時にdispatchが走ってしまい、DOMが存在しない可能性がある
41
+ // effect_initializeNodesを機能させるため、dispatch を描画後まで保留する
42
+ requestAnimationFrame(() => {
43
+ dispatch((state) => action(state, e));
44
+ });
45
+ };
46
+ return [newState, effect];
47
+ };
48
+ // ---------- ---------- ---------- ---------- ----------
49
+ // getClassList
50
+ // ---------- ---------- ---------- ---------- ----------
51
+ /**
52
+ * props から classList を取得
53
+ *
54
+ * @param {Record<string, any>} props - props
55
+ * @returns {string[]}
56
+ */
57
+ export const getClassList = (props) => {
58
+ return props.class
59
+ ? props.class.trim().split(" ").filter(Boolean)
60
+ : [];
61
+ };
62
+ // ---------- ---------- ---------- ---------- ----------
63
+ // deleteKeys
64
+ // ---------- ---------- ---------- ---------- ----------
65
+ /**
66
+ * props から不要なキーを削除する
67
+ *
68
+ * @template T
69
+ * @param {T} props - props
70
+ * @param {(keyof T)[])} keys - 削除するキー
71
+ * @returns {Omit<T, (typeof keys)[number]>}
72
+ */
73
+ export const deleteKeys = (props, ...keys) => {
74
+ const result = { ...props };
75
+ keys.forEach(key => delete result[key]);
76
+ return result;
77
+ };
78
+ // ========== ========== ========== ========== ==========
79
+ // コンポーネント
80
+ // ========== ========== ========== ========== ==========
81
+ // ---------- ---------- ---------- ---------- ----------
82
+ // Route
83
+ // ---------- ---------- ---------- ---------- ----------
84
+ /**
85
+ * ステート内の文字とmatchした時、VNodeを返す
86
+ *
87
+ * @template S
88
+ * @param {Record<string, any>} props - props
89
+ * @param {S} props.state - ステート
90
+ * @param {string[]} props.keyNames - ステート内の文字までのパス
91
+ * @param {string} props.match - 一致判定する文字
92
+ * @param {any} children - 出力する内容 (VNode / 配列 / 文字など)
93
+ * @returns {VNode<S> | null}
94
+ */
95
+ export const Route = function (props, children) {
96
+ const { state, keyNames, match } = props;
97
+ const selectedName = getValue(state, keyNames, "");
98
+ // nullの場合、VNodeは生成されない
99
+ return selectedName === match ? children : null;
100
+ };
101
+ // ---------- ---------- ---------- ---------- ----------
102
+ // SelectButton
103
+ // ---------- ---------- ---------- ---------- ----------
104
+ const REVERSE_PREFIX = "r_";
105
+ /**
106
+ * クリックで、クラス名のselectをトグルするボタン
107
+ *
108
+ * @template S
109
+ * @param {Record<string, any>} props - props
110
+ * @param {S} props.state - ステート
111
+ * @param {string[]} props.keyNames - ステート内の文字配列までのパス
112
+ * @param {string} props.id - ユニークID
113
+ * @param {boolean} [props.reverse] - 反転選択するか
114
+ * @param {any} children - 子要素 (VNode / string / 配列など)
115
+ * @returns {VNode<S>}
116
+ */
117
+ export const SelectButton = function (props, children) {
118
+ const { state, keyNames, id, reverse = false } = props;
119
+ // classList
120
+ const classList = getClassList(props).filter(item => {
121
+ const name = item.toLowerCase();
122
+ return name !== "select" && name !== "reverse";
123
+ });
124
+ const selectedNames = getValue(state, keyNames, []);
125
+ if (selectedNames.includes(id))
126
+ classList.push("select");
127
+ if (selectedNames.includes(`${REVERSE_PREFIX}${id}`))
128
+ classList.push("reverse");
129
+ // action
130
+ const action = (state, e) => {
131
+ const selectedNames = getValue(state, keyNames, []);
132
+ const newList = selectedNames.includes(id)
133
+ ? reverse
134
+ ? selectedNames.filter(item => item !== id).concat(`${REVERSE_PREFIX}${id}`)
135
+ : selectedNames.filter(item => item !== id)
136
+ : selectedNames.includes(`${REVERSE_PREFIX}${id}`)
137
+ ? selectedNames.filter(item => item !== `${REVERSE_PREFIX}${id}`)
138
+ : selectedNames.concat(id);
139
+ const newState = setValue(state, keyNames, newList);
140
+ return concatAction(props.onclick, newState, e);
141
+ };
142
+ // VNode
143
+ return button({
144
+ type: "button",
145
+ ...deleteKeys(props, "state", "keyNames", "reverse"),
146
+ class: classList.join(" "),
147
+ onclick: action
148
+ }, children);
149
+ };
150
+ // ---------- ---------- ---------- ---------- ----------
151
+ // OptionButton
152
+ // ---------- ---------- ---------- ---------- ----------
153
+ /**
154
+ * クリックで、クラス名のselectを排他的に選択するボタン
155
+ *
156
+ * @template S
157
+ * @param {Record<string, any>} props - props
158
+ * @param {S} props.state - ステート
159
+ * @param {string[]} props.keyNames - ステート内の文字までのパス
160
+ * @param {string} props.id - ユニークID
161
+ * @param {boolean} [props.reverse] - 反転選択するか
162
+ * @param {any} children - 子要素 (VNode / string / 配列など)
163
+ * @returns {VNode<S>}
164
+ */
165
+ export const OptionButton = function (props, children) {
166
+ const { state, keyNames, id, reverse = false } = props;
167
+ // classList
168
+ const classList = getClassList(props).filter(item => {
169
+ const name = item.toLowerCase();
170
+ return name !== "select" && name !== "reverse";
171
+ });
172
+ const selectedName = getValue(state, keyNames, "");
173
+ if (selectedName === id)
174
+ classList.push("select");
175
+ if (selectedName === `${REVERSE_PREFIX}${id}`)
176
+ classList.push("reverse");
177
+ // action
178
+ const action = (state, e) => {
179
+ const selectedName = getValue(state, keyNames, "");
180
+ const newValue = selectedName === id && reverse
181
+ ? `${REVERSE_PREFIX}${id}`
182
+ : id;
183
+ const newState = setValue(state, keyNames, newValue);
184
+ return concatAction(props.onclick, newState, e);
185
+ };
186
+ // VNode
187
+ return button({
188
+ type: "button",
189
+ ...deleteKeys(props, "state", "keyNames", "reverse"),
190
+ class: classList.join(" "),
191
+ onclick: action
192
+ }, children);
193
+ };
@@ -0,0 +1,2 @@
1
+ export { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./state";
2
+ export { el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./component";
@@ -0,0 +1,2 @@
1
+ export { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./state";
2
+ export { el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./component";
@@ -0,0 +1,54 @@
1
+ /**
2
+ * パスを辿って、ステートから値を取得する
3
+ *
4
+ * @template S
5
+ * @template D
6
+ * @param {S} state - ステート
7
+ * @param {string[]} keyNames - 値までのパス
8
+ * @param {D} def - デフォルト値
9
+ * @returns {D} - 型保証は呼び出し側の責任
10
+ */
11
+ export declare const getValue: <S, D>(state: S, keyNames: string[], def: D) => D;
12
+ /**
13
+ * パスを辿って、ステートに値を設定して返す
14
+ *
15
+ * @template S
16
+ * @param {S} state - ステート
17
+ * @param {string[]} keyNames - 値までのパス
18
+ * @param {any} value - 設定する値
19
+ * @returns {S}
20
+ */
21
+ export declare const setValue: <S>(state: S, keyNames: string[], value: any) => S;
22
+ /**
23
+ * IDからユニーク文字列を作成する
24
+ *
25
+ * @param {string} id - ユニークID
26
+ * @returns {string}
27
+ */
28
+ export declare const createLocalKey: (id: string) => string;
29
+ /**
30
+ * ステートから、ローカルステートを取得する
31
+ *
32
+ * @template S
33
+ * @param {S} state - ステート
34
+ * @param {string} id - ユニークID
35
+ * @param {Record<string, any>} def - 初期値
36
+ * @returns {Record<string, any>}
37
+ */
38
+ export declare const getLocalState: <S>(state: S, id: string, def: {
39
+ [key: string]: any;
40
+ }) => {
41
+ [key: string]: any;
42
+ };
43
+ /**
44
+ * ローカルステートを更新してステートを返す
45
+ *
46
+ * @template S
47
+ * @param {S} state - ステート
48
+ * @param {string} id - ユニークID
49
+ * @param {Record<string, any>} value - 設定するローカルステート
50
+ * @returns {S}
51
+ */
52
+ export declare const setLocalState: <S>(state: S, id: string, value: {
53
+ [key: string]: any;
54
+ }) => S;
@@ -0,0 +1,118 @@
1
+ // hyperapp-ut / core / state.ts
2
+ // ---------- ---------- ---------- ---------- ----------
3
+ // getValue
4
+ // ---------- ---------- ---------- ---------- ----------
5
+ /**
6
+ * パスを辿って、ステートから値を取得する
7
+ *
8
+ * @template S
9
+ * @template D
10
+ * @param {S} state - ステート
11
+ * @param {string[]} keyNames - 値までのパス
12
+ * @param {D} def - デフォルト値
13
+ * @returns {D} - 型保証は呼び出し側の責任
14
+ */
15
+ export const getValue = function (state, keyNames, def) {
16
+ let result = state;
17
+ for (const key of keyNames) {
18
+ if (result == null ||
19
+ typeof result !== "object")
20
+ return def;
21
+ if (Object.prototype.hasOwnProperty.call(result, key)) {
22
+ result = result[key];
23
+ }
24
+ else {
25
+ return def;
26
+ }
27
+ }
28
+ return result;
29
+ };
30
+ // ---------- ---------- ---------- ---------- ----------
31
+ // setValue
32
+ // ---------- ---------- ---------- ---------- ----------
33
+ /**
34
+ * パスを辿って、ステートに値を設定して返す
35
+ *
36
+ * @template S
37
+ * @param {S} state - ステート
38
+ * @param {string[]} keyNames - 値までのパス
39
+ * @param {any} value - 設定する値
40
+ * @returns {S}
41
+ */
42
+ export const setValue = function (state, keyNames, value) {
43
+ let result = { ...state };
44
+ let current = result;
45
+ for (let i = 0; i < keyNames.length; i++) {
46
+ const key = keyNames[i];
47
+ if (Object.prototype.hasOwnProperty.call(current, key) &&
48
+ current[key] != null &&
49
+ typeof current[key] === "object") {
50
+ current[key] = { ...current[key] };
51
+ }
52
+ else {
53
+ current[key] = {};
54
+ }
55
+ if (keyNames.length - 1 === i) {
56
+ current[key] = value;
57
+ }
58
+ current = current[key];
59
+ }
60
+ return result;
61
+ };
62
+ // ---------- ---------- ---------- ---------- ----------
63
+ // createLocalKey
64
+ // ---------- ---------- ---------- ---------- ----------
65
+ /**
66
+ * IDからユニーク文字列を作成する
67
+ *
68
+ * @param {string} id - ユニークID
69
+ * @returns {string}
70
+ */
71
+ export const createLocalKey = (id) => `local_key_${id}`;
72
+ // ---------- ---------- ---------- ---------- ----------
73
+ // getLocalState
74
+ // ---------- ---------- ---------- ---------- ----------
75
+ /**
76
+ * ステートから、ローカルステートを取得する
77
+ *
78
+ * @template S
79
+ * @param {S} state - ステート
80
+ * @param {string} id - ユニークID
81
+ * @param {Record<string, any>} def - 初期値
82
+ * @returns {Record<string, any>}
83
+ */
84
+ export const getLocalState = function (state, id, def) {
85
+ const localKey = createLocalKey(id);
86
+ const obj = Object.prototype.hasOwnProperty.call(state, localKey)
87
+ ? state[localKey]
88
+ : {};
89
+ return {
90
+ ...def,
91
+ ...obj
92
+ };
93
+ };
94
+ // ---------- ---------- ---------- ---------- ----------
95
+ // setLocalState
96
+ // ---------- ---------- ---------- ---------- ----------
97
+ /**
98
+ * ローカルステートを更新してステートを返す
99
+ *
100
+ * @template S
101
+ * @param {S} state - ステート
102
+ * @param {string} id - ユニークID
103
+ * @param {Record<string, any>} value - 設定するローカルステート
104
+ * @returns {S}
105
+ */
106
+ export const setLocalState = function (state, id, value) {
107
+ const localKey = createLocalKey(id);
108
+ const obj = Object.prototype.hasOwnProperty.call(state, localKey)
109
+ ? state[localKey]
110
+ : {};
111
+ return {
112
+ ...state,
113
+ [localKey]: {
114
+ ...obj,
115
+ ...value
116
+ }
117
+ };
118
+ };
@@ -0,0 +1,2 @@
1
+ export type { ScrollMargin, MatrixState } from "./utils";
2
+ export { getScrollMargin, getMatrixState, marquee } from "./utils";
@@ -0,0 +1 @@
1
+ export { getScrollMargin, getMatrixState, marquee } from "./utils";
@@ -0,0 +1,68 @@
1
+ /**
2
+ * スクロールの余白
3
+ *
4
+ * @type {Object} ScrollMargin
5
+ * @property {number} top - 上までの余白
6
+ * @property {number} left - 左までの余白
7
+ * @property {number} right - 右までの余白
8
+ * @property {number} bottom - 下までの余白
9
+ */
10
+ export interface ScrollMargin {
11
+ top: number;
12
+ left: number;
13
+ right: number;
14
+ bottom: number;
15
+ }
16
+ /**
17
+ * スクロールの余白を取得する
18
+ *
19
+ * @param {Event} e - イベント
20
+ * @returns {ScrollMargin}
21
+ */
22
+ export declare const getScrollMargin: (e: Event) => ScrollMargin;
23
+ /**
24
+ * transform 情報
25
+ */
26
+ export interface MatrixState {
27
+ translate: {
28
+ x: number;
29
+ y: number;
30
+ z: number;
31
+ };
32
+ scale: {
33
+ x: number;
34
+ y: number;
35
+ z: number;
36
+ };
37
+ rotate: {
38
+ x: number;
39
+ y: number;
40
+ z: number;
41
+ };
42
+ }
43
+ /**
44
+ * DOM から transfrom 情報を取得する
45
+ *
46
+ * @param {HTMLElement} dom - 情報を取得する DOM
47
+ * @returns {MatrixState}
48
+ */
49
+ export declare const getMatrixState: (dom: HTMLElement) => MatrixState | null;
50
+ /**
51
+ * Carousel 風に DOM が流れるアニメーションを実行する
52
+ *
53
+ * @param {Object} props - props
54
+ * @param {HTMLElement} props.element - DOM
55
+ * @param {number} props.duration - 実行時間 (ms)
56
+ * @param {number} props.interval - 待機時間 (ms)
57
+ * @param {(t: number) => number} [props.easing] - easing 関数
58
+ * @returns {{start: () => void, stop: () => void}}
59
+ */
60
+ export declare const marquee: <S>(props: {
61
+ element: HTMLElement;
62
+ duration: number;
63
+ interval: number;
64
+ easing?: (t: number) => number;
65
+ }) => {
66
+ start: () => void;
67
+ stop: () => void;
68
+ };
@@ -0,0 +1,159 @@
1
+ // hyperapp-ui / dom / utils.ts
2
+ // ---------- ---------- ---------- ---------- ----------
3
+ // getScrollMargin
4
+ // ---------- ---------- ---------- ---------- ----------
5
+ /**
6
+ * スクロールの余白を取得する
7
+ *
8
+ * @param {Event} e - イベント
9
+ * @returns {ScrollMargin}
10
+ */
11
+ export const getScrollMargin = function (e) {
12
+ const el = e.currentTarget;
13
+ if (!el)
14
+ return { top: 0, left: 0, right: 0, bottom: 0 };
15
+ return {
16
+ top: el.scrollTop,
17
+ left: el.scrollLeft,
18
+ right: el.scrollWidth - (el.clientWidth + el.scrollLeft),
19
+ bottom: el.scrollHeight - (el.clientHeight + el.scrollTop)
20
+ };
21
+ };
22
+ // ---------- ---------- ---------- ---------- ----------
23
+ // getMatrixState
24
+ // ---------- ---------- ---------- ---------- ----------
25
+ /**
26
+ * DOM から transfrom 情報を取得する
27
+ *
28
+ * @param {HTMLElement} dom - 情報を取得する DOM
29
+ * @returns {MatrixState}
30
+ */
31
+ export const getMatrixState = (dom) => {
32
+ const style = getComputedStyle(dom);
33
+ const transform = style.transform;
34
+ if (!transform || transform === 'none')
35
+ return null;
36
+ let m;
37
+ try {
38
+ m = new DOMMatrix(transform);
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ const scaleX = Math.hypot(m.m11, m.m12, m.m13);
44
+ const scaleY = Math.hypot(m.m21, m.m22, m.m23);
45
+ const scaleZ = Math.hypot(m.m31, m.m32, m.m33);
46
+ let rotateX = 0;
47
+ let rotateY = 0;
48
+ let rotateZ = 0;
49
+ if (scaleX && scaleY && scaleZ) {
50
+ rotateY = Math.asin(-m.m13 / scaleZ);
51
+ const EPS = 1e-8;
52
+ if (Math.cos(rotateY) > EPS) {
53
+ rotateX = Math.atan2(m.m23 / scaleZ, m.m33 / scaleZ);
54
+ rotateZ = Math.atan2(m.m12 / scaleY, m.m11 / scaleX);
55
+ }
56
+ }
57
+ return {
58
+ translate: {
59
+ x: m.m41,
60
+ y: m.m42,
61
+ z: m.m43
62
+ },
63
+ scale: {
64
+ x: scaleX,
65
+ y: scaleY,
66
+ z: scaleZ
67
+ },
68
+ // radian
69
+ rotate: {
70
+ x: rotateX,
71
+ y: rotateY,
72
+ z: rotateZ
73
+ }
74
+ };
75
+ };
76
+ // ---------- ---------- ---------- ---------- ----------
77
+ // marquee
78
+ // ---------- ---------- ---------- ---------- ----------
79
+ /**
80
+ * Carousel 風に DOM が流れるアニメーションを実行する
81
+ *
82
+ * @param {Object} props - props
83
+ * @param {HTMLElement} props.element - DOM
84
+ * @param {number} props.duration - 実行時間 (ms)
85
+ * @param {number} props.interval - 待機時間 (ms)
86
+ * @param {(t: number) => number} [props.easing] - easing 関数
87
+ * @returns {{start: () => void, stop: () => void}}
88
+ */
89
+ export const marquee = function (props) {
90
+ const { element, duration, interval, easing = (t) => t } = props;
91
+ // function calcWidth
92
+ const calcWidth = () => {
93
+ const children = Array.from(element.children);
94
+ return !children || children.length < 2
95
+ ? 0
96
+ : children[1].offsetLeft - children[0].offsetLeft;
97
+ };
98
+ // variable
99
+ let rID = 0;
100
+ let timerID = 0;
101
+ let startTime = 0;
102
+ let width = 0;
103
+ // requestAnimationFrame callback
104
+ const action = (now) => {
105
+ // set startTime
106
+ if (startTime === 0)
107
+ startTime = now;
108
+ // get progress
109
+ const progress = Math.min((now - startTime) / Math.max(1, duration));
110
+ // set property
111
+ element.style.transform = `translateX(${-easing(progress) * width}px)`;
112
+ // next
113
+ if (progress < 1) {
114
+ rID = requestAnimationFrame(action);
115
+ return;
116
+ }
117
+ // reset property
118
+ element.style.transform = `translateX(0px)`;
119
+ // set children
120
+ const firstChild = element.children[0];
121
+ if (!firstChild)
122
+ return;
123
+ // loop
124
+ element.appendChild(firstChild);
125
+ // loop
126
+ timerID = window.setTimeout(() => {
127
+ startTime = 0;
128
+ rID = requestAnimationFrame(action);
129
+ }, interval);
130
+ };
131
+ // result
132
+ return {
133
+ start: () => {
134
+ // 二重起動防止
135
+ if (rID !== 0)
136
+ return;
137
+ // get width
138
+ width = calcWidth();
139
+ if (width === 0)
140
+ return;
141
+ // set gpu layer
142
+ element.style.willChange = "transform";
143
+ // start animation
144
+ rID = requestAnimationFrame(action);
145
+ },
146
+ stop: () => {
147
+ // cancel animation
148
+ cancelAnimationFrame(rID);
149
+ // stop timer
150
+ clearTimeout(timerID);
151
+ // clear gpy layer
152
+ element.style.willChange = "";
153
+ element.style.transform = "";
154
+ // clear ID
155
+ rID = 0;
156
+ timerID = 0;
157
+ }
158
+ };
159
+ };
@@ -0,0 +1,7 @@
1
+ export { getValue, setValue, getLocalState, setLocalState, createLocalKey, el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./core";
2
+ export type { InternalEffect, RAFEvent, CSSProperty } from "./animation";
3
+ export { RAFTask, subscription_RAFManager, progress_easing, createUnits, createRAFProperties, effect_RAFProperties } from "./animation";
4
+ export type { CarouselState, CarouselController } from "./animationView";
5
+ export { Carousel, effect_InitCarousel } from "./animationView";
6
+ export type { ScrollMargin, MatrixState } from "./dom";
7
+ export { getScrollMargin, getMatrixState, marquee } from "./dom";
@@ -0,0 +1,5 @@
1
+ // core
2
+ export { getValue, setValue, getLocalState, setLocalState, createLocalKey, el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./core";
3
+ export { RAFTask, subscription_RAFManager, progress_easing, createUnits, createRAFProperties, effect_RAFProperties } from "./animation";
4
+ export { Carousel, effect_InitCarousel } from "./animationView";
5
+ export { getScrollMargin, getMatrixState, marquee } from "./dom";
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "hyperapp-is",
3
+ "version": "0.1.0",
4
+ "description": "UI foundation library for Hyperapp by is4416",
5
+ "license": "MIT",
6
+ "type": "module",
7
+
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "files": ["dist"],
11
+
12
+ "readme": "README.npm.md",
13
+
14
+ "scripts": {
15
+ "build": "npm run build:lib",
16
+ "build:lib": "tsc -p tsconfig.lib.json",
17
+ "build:docs": "vite build",
18
+ "dev": "vite",
19
+ "pack:check": "npm pack",
20
+ "test": "echo \"Error: no test specified\" && exit 1"
21
+ },
22
+
23
+ "keywords": [
24
+ "hyperapp",
25
+ "ui",
26
+ "animation",
27
+ "raf",
28
+ "carousel"
29
+ ],
30
+
31
+ "peerDependencies": {
32
+ "hyperapp": "^2.0.0",
33
+ "hyperapp-jsx-pragma": "^1.3.0"
34
+ },
35
+
36
+ "devDependencies": {
37
+ "typescript": "^5.0.0",
38
+ "vite": "^7.3.0"
39
+ }
40
+ }