@geckou/ui-core 0.2.0 → 0.3.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.
@@ -22,4 +22,5 @@ export declare const MESSAGES: {
22
22
  invalidDay: string;
23
23
  monthOutOfRange: string;
24
24
  dayOutOfRange: (maxDay: number) => string;
25
+ startAfterEnd: string;
25
26
  };
package/dist/constants.js CHANGED
@@ -63,4 +63,5 @@ export const MESSAGES = {
63
63
  invalidDay: '日は2桁の数字で入力してください',
64
64
  monthOutOfRange: '月は01から12の間で入力してください',
65
65
  dayOutOfRange: (maxDay) => `日は01から${maxDay}の間で入力してください`,
66
+ startAfterEnd: '終了日より後の日付は選べません',
66
67
  };
package/dist/date.js CHANGED
@@ -76,6 +76,12 @@ export function composeDateValue(dateObject, type = 'date') {
76
76
  if (parts.some((part) => !part)) {
77
77
  return '';
78
78
  }
79
+ // 数字でない入力('ab' 等)を pad(Number(part)) に通すと '2024-NaN-01' のような
80
+ // 日付でない文字列ができる。Number.isFinite だと '1.5' / '0x0a' / ' 1' を通して
81
+ // しまうので、validateDateObject と同じ isNumeric で判定する
82
+ if (parts.some((part) => !isNumeric(part))) {
83
+ return '';
84
+ }
79
85
  const [yearPart, ...rest] = parts;
80
86
  return [yearPart, ...rest.map((part) => pad(Number(part)))].join('-');
81
87
  }
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export * from './validation.js';
4
4
  export * from './date.js';
5
5
  export * from './text.js';
6
6
  export * from './form-validation-store.js';
7
+ export * from './scroll-lock.js';
package/dist/index.js CHANGED
@@ -4,3 +4,4 @@ export * from './validation.js';
4
4
  export * from './date.js';
5
5
  export * from './text.js';
6
6
  export * from './form-validation-store.js';
7
+ export * from './scroll-lock.js';
@@ -0,0 +1,7 @@
1
+ export type ScrollLock = {
2
+ /** 引数の真偽でロック・解除を切り替える。同じ状態の連続呼び出しは無視される */
3
+ toggle: (shouldLock: boolean) => void;
4
+ /** アンマウント時に呼ぶ。ロック中なら解除する */
5
+ release: () => void;
6
+ };
7
+ export declare function createScrollLock(): ScrollLock;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ページ全体のスクロールロック。
3
+ *
4
+ * モーダルを重ねても解除順で壊れないよう、ロック数をカウントする。
5
+ * 最初のロックで元の `overflow` を控え、最後の解除で戻す
6
+ * (無条件に `''` にすると、アプリ側が持っていたインラインの `overflow` が消える)。
7
+ *
8
+ * 呼び出し側は 1 コンポーネント 1 ハンドルを持ち、表示状態を `toggle()` に渡して、
9
+ * アンマウント時に `release()` する。同じハンドルから同じ状態を二度要求しても
10
+ * 数え間違えない。
11
+ */
12
+ let lockCount = 0;
13
+ let previousOverflow = '';
14
+ function getBody() {
15
+ // SSR では document が無い(Nuxt / Next.js のサーバー側)
16
+ const doc = globalThis.document;
17
+ return doc?.body ?? null;
18
+ }
19
+ export function createScrollLock() {
20
+ let isLocked = false;
21
+ const toggle = (shouldLock) => {
22
+ const body = getBody();
23
+ if (!body || isLocked === shouldLock)
24
+ return;
25
+ isLocked = shouldLock;
26
+ lockCount += shouldLock ? 1 : -1;
27
+ if (lockCount === 1 && shouldLock) {
28
+ previousOverflow = body.style.overflow;
29
+ body.style.overflow = 'hidden';
30
+ }
31
+ else if (lockCount <= 0) {
32
+ lockCount = 0;
33
+ body.style.overflow = previousOverflow;
34
+ }
35
+ };
36
+ return { toggle, release: () => toggle(false) };
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geckou/ui-core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-agnostic logic shared by @geckou/ui-vue and @geckou/ui-react",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,8 +34,8 @@
34
34
  },
35
35
  "scripts": {
36
36
  "build": "rm -rf dist && tsc -p tsconfig.build.json",
37
- "lint": "eslint src",
38
- "lint:fix": "eslint src --fix",
37
+ "lint": "eslint src tests",
38
+ "lint:fix": "eslint src tests --fix",
39
39
  "prepublishOnly": "yarn build",
40
40
  "test": "vitest run",
41
41
  "test:watch": "vitest",