@longzai-intelligence-layout/primitives 0.0.0-stage → 0.0.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.
@@ -0,0 +1,168 @@
1
+ import { PreferenceDefinition } from "@longzai-intelligence-layout/preferences";
2
+ import { ReactNode } from "react";
3
+ /**
4
+ * 可调宽列宽度界
5
+ */
6
+ type PaneWidthBounds = {
7
+ /**
8
+ * 默认宽度,像素,双击把手复位到此值
9
+ */
10
+ defaultWidth: number;
11
+ /**
12
+ * 最小宽度,像素,调宽候选不得低于此值,保住主区可用宽度
13
+ */
14
+ minWidth: number;
15
+ /**
16
+ * 最大宽度,像素,调宽候选不得高于此值,避免主区被挤塌
17
+ */
18
+ maxWidth: number;
19
+ };
20
+ /**
21
+ * 可调高面板行高度界
22
+ */
23
+ type PaneHeightBounds = {
24
+ /**
25
+ * 默认高度,像素,双击把手复位到此值
26
+ */
27
+ defaultHeight: number;
28
+ /**
29
+ * 最小高度,像素,调高候选不得低于此值,保住主区可用高度
30
+ */
31
+ minHeight: number;
32
+ /**
33
+ * 最大高度,像素,调高候选不得高于此值,避免主区被挤塌
34
+ */
35
+ maxHeight: number;
36
+ };
37
+ /**
38
+ * 构造列宽度偏好定义
39
+ *
40
+ * @remarks
41
+ * 键缺失与非法取值回落默认宽度,可解析但越界的取值钳制到界内并取整
42
+ * @param key - 完整存储键名,约定挂消费方命名空间前缀
43
+ * @param tier - 偏好存储层级
44
+ * @param bounds - 列宽度界
45
+ * @returns 列宽度偏好定义
46
+ */
47
+ declare function definePaneWidthPreference(key: string, tier: 'persistent' | 'session', bounds: PaneWidthBounds): PreferenceDefinition<number>;
48
+ /**
49
+ * 构造面板行高度偏好定义
50
+ *
51
+ * @remarks
52
+ * 键缺失与非法取值回落默认高度,可解析但越界的取值钳制到界内并取整
53
+ * @param key - 完整存储键名,约定挂消费方命名空间前缀
54
+ * @param tier - 偏好存储层级
55
+ * @param bounds - 面板行高度界
56
+ * @returns 面板行高度偏好定义
57
+ */
58
+ declare function definePaneHeightPreference(key: string, tier: 'persistent' | 'session', bounds: PaneHeightBounds): PreferenceDefinition<number>;
59
+ /**
60
+ * 可调面板分隔把手组件
61
+ *
62
+ * 以细分隔条形态承载面板尺寸的指针拖拽、键盘步进与双击复位交互,
63
+ * 竖向把手调节列宽,横向把手调节行高,
64
+ * 视觉为悬停加深的一条细分隔线,拖拽中切换为强调色
65
+ */
66
+ /**
67
+ * 把手朝向
68
+ *
69
+ * `vertical` 为竖向分隔条承载列宽调节,`horizontal` 为横向分隔条承载行高调节
70
+ */
71
+ type PaneResizeOrientation = 'vertical' | 'horizontal';
72
+ /**
73
+ * 被调面板方位
74
+ *
75
+ * `above` 为被调面板在把手上方,`below` 为被调面板在把手下方,仅横向把手消费,
76
+ * `below` 时拖拽增量与键盘步进方向整体取反,让背离下方面板的拖拽即增高
77
+ */
78
+ type PaneResizeTarget = 'above' | 'below';
79
+ /**
80
+ * 分隔把手组件属性
81
+ */
82
+ type PaneResizeHandleProps = {
83
+ /**
84
+ * 把手朝向,缺省竖向即列宽把手
85
+ *
86
+ * @default 'vertical'
87
+ */
88
+ orientation?: PaneResizeOrientation;
89
+ /**
90
+ * 被调面板方位,仅横向把手消费,缺省被调面板在把手上方
91
+ *
92
+ * @remarks
93
+ * 取 `below` 时拖拽增量与键盘步进方向整体取反,
94
+ * 适配底部停靠面板即被调面板在把手下方的装配形态
95
+ * @default 'above'
96
+ */
97
+ resizeTarget?: PaneResizeTarget;
98
+ /**
99
+ * 当前面板尺寸,像素,列宽或行高,用于无障碍值播报与键盘步进基准
100
+ */
101
+ size: number;
102
+ /**
103
+ * 尺寸下界,像素
104
+ */
105
+ minSize: number;
106
+ /**
107
+ * 尺寸上界,像素
108
+ */
109
+ maxSize: number;
110
+ /**
111
+ * 无障碍名称,说明该把手调节哪一面板
112
+ */
113
+ ariaLabel: string;
114
+ /**
115
+ * 候选尺寸变更动作,候选经面板尺寸钩子钳制后生效
116
+ */
117
+ onSizeChange: (candidate: number) => void;
118
+ /**
119
+ * 双击复位动作
120
+ */
121
+ onReset: () => void;
122
+ };
123
+ /**
124
+ * 可调面板分隔把手组件
125
+ *
126
+ * @param props - 组件属性
127
+ * @returns 分隔把手元素
128
+ */
129
+ declare function PaneResizeHandle(props: PaneResizeHandleProps): import("react").JSX.Element;
130
+ /**
131
+ * 可调宽列组件属性
132
+ */
133
+ type ResizableColumnProps = {
134
+ /**
135
+ * 列元素标签,侧栏语义用 `aside`,普通双栏列用 `div`
136
+ *
137
+ * @default 'div'
138
+ */
139
+ as?: 'aside' | 'div';
140
+ /**
141
+ * 列宽度偏好定义
142
+ */
143
+ preference: PreferenceDefinition<number>;
144
+ /**
145
+ * 列宽度界,供分隔把手拖拽钳制与复位
146
+ */
147
+ bounds: PaneWidthBounds;
148
+ /**
149
+ * 把手无障碍名称,说明调节哪一列
150
+ */
151
+ ariaLabel: string;
152
+ /**
153
+ * 列元素附加类名,承载滚动与背景等外观
154
+ */
155
+ className?: string;
156
+ /**
157
+ * 列内容
158
+ */
159
+ children: ReactNode;
160
+ };
161
+ /**
162
+ * 可调宽列组件
163
+ *
164
+ * @param props - 组件属性
165
+ * @returns 列元素与分隔把手片段
166
+ */
167
+ declare function ResizableColumn(props: ResizableColumnProps): import("react").JSX.Element;
168
+ export { type PaneHeightBounds, PaneResizeHandle, type PaneResizeHandleProps, type PaneResizeOrientation, type PaneResizeTarget, type PaneWidthBounds, ResizableColumn, type ResizableColumnProps, definePaneHeightPreference, definePaneWidthPreference };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{clampedNumberCodec as e,definePreference as t,usePreference as n}from"@longzai-intelligence-layout/preferences";import{Fragment as r,useCallback as i,useEffect as a,useRef as o,useState as s}from"react";import{jsx as c,jsxs as l}from"react/jsx-runtime";function u(n,r,i){return t({key:n,tier:r},e({fallback:i.defaultWidth,min:i.minWidth,max:i.maxWidth}))}function d(n,r,i){return t({key:n,tier:r},e({fallback:i.defaultHeight,min:i.minHeight,max:i.maxHeight}))}function f(e,t){let{isVertical:n,deltaSign:r,size:i,minSize:a,maxSize:o,onSizeChange:s}=t,c=null;n?e.key===`ArrowLeft`||e.key===`ArrowDown`?c=-16:(e.key===`ArrowRight`||e.key===`ArrowUp`)&&(c=16):e.key===`ArrowUp`||e.key===`ArrowLeft`?c=-16:(e.key===`ArrowDown`||e.key===`ArrowRight`)&&(c=16),c===null?e.key===`Home`?(e.preventDefault(),s(a)):e.key===`End`&&(e.preventDefault(),s(o)):(e.preventDefault(),s(i+r*c))}function p(e,t){a(()=>{if(!e)return;let n=document.body.style.userSelect,r=document.body.style.cursor;return document.body.style.userSelect=`none`,document.body.style.cursor=t?`col-resize`:`row-resize`,()=>{document.body.style.userSelect=n,document.body.style.cursor=r}},[e,t])}function m(e){let t=e.orientation??`vertical`,n=t===`vertical`,r=(e.resizeTarget??`above`)===`below`?-1:1,{size:i,minSize:a,maxSize:l,ariaLabel:u,onSizeChange:d,onReset:m}=e,[h,g]=s(!1),_=o({pointerCoordinate:0,startSize:0});return p(h,n),/* @__PURE__ */ c(`div`,{role:`separator`,"aria-orientation":t,"aria-label":u,"aria-valuenow":i,"aria-valuemin":a,"aria-valuemax":l,"aria-valuetext":`${i} 像素`,tabIndex:0,title:n?`拖拽调宽,双击复位`:`拖拽调高,双击复位`,onPointerDown:e=>{e.preventDefault(),e.currentTarget.setPointerCapture(e.pointerId),_.current={pointerCoordinate:n?e.clientX:e.clientY,startSize:i},g(!0)},onPointerMove:e=>{if(!h)return;let t=n?e.clientX:e.clientY;d(_.current.startSize+r*(t-_.current.pointerCoordinate))},onPointerUp:e=>{e.currentTarget.hasPointerCapture(e.pointerId)&&e.currentTarget.releasePointerCapture(e.pointerId),g(!1)},onPointerCancel:()=>{g(!1)},onDoubleClick:m,onKeyDown:e=>{f(e,{isVertical:n,deltaSign:r,size:i,minSize:a,maxSize:l,onSizeChange:d})},className:n?`group relative w-1.5 shrink-0 cursor-col-resize touch-none select-none`:`group relative h-1.5 shrink-0 cursor-row-resize touch-none select-none`,children:/* @__PURE__ */ c(`span`,{className:n?`absolute inset-y-0 left-1/2 -translate-x-1/2 ${h?`w-0.5 bg-primary`:`w-px bg-border group-hover:bg-muted-foreground/40`}`:`absolute inset-x-0 top-1/2 -translate-y-1/2 ${h?`h-0.5 bg-primary`:`h-px bg-border group-hover:bg-muted-foreground/40`}`})})}function h(e,t){let{value:r,change:a}=n(e);return{width:r,changeWidth:a,resetWidth:i(()=>{a(t.defaultWidth)},[t,a])}}function g(e){let t=e.as??`div`,n=h(e.preference,e.bounds);return/* @__PURE__ */ l(r,{children:[/* @__PURE__ */ c(t,{className:`shrink-0 ${e.className??``}`,style:{width:n.width},children:e.children}),/* @__PURE__ */ c(m,{orientation:`vertical`,size:n.width,minSize:e.bounds.minWidth,maxSize:e.bounds.maxWidth,ariaLabel:e.ariaLabel,onSizeChange:n.changeWidth,onReset:n.resetWidth})]})}export{m as PaneResizeHandle,g as ResizableColumn,d as definePaneHeightPreference,u as definePaneWidthPreference};
package/package.json CHANGED
@@ -1,6 +1,57 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-layout/primitives",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.1",
4
+ "description": "Longzai Intelligence 布局结构原语包:分栏、面板与尺寸 hooks",
5
+ "keywords": [
6
+ "layout",
7
+ "longzai-intelligence",
8
+ "primitives",
9
+ "resizable"
10
+ ],
11
+ "license": "UNLICENSED",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "lzi-builder",
27
+ "build:prod": "NODE_ENV=production bun run build",
28
+ "prepublishOnly": "bun run build:prod",
29
+ "typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
30
+ "typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
31
+ "typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
32
+ "typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
33
+ "lint": "oxlint && oxfmt --check",
34
+ "lint:fix": "oxlint --fix && oxfmt",
35
+ "test": "bun test",
36
+ "test:watch": "bun test --watch",
37
+ "test:coverage": "bun test --coverage",
38
+ "test:unit": "bun test src/__tests__/unit/",
39
+ "clean": "lzi-dev-cli clean"
40
+ },
41
+ "dependencies": {
42
+ "@longzai-intelligence-layout/preferences": "0.0.1"
43
+ },
44
+ "devDependencies": {
45
+ "@happy-dom/global-registrator": "^20.11.2",
46
+ "@testing-library/react": "^16.3.2",
47
+ "@types/react": "^19.2.17",
48
+ "@types/react-dom": "^19.3.0",
49
+ "happy-dom": "^20.11.2",
50
+ "react": "19.2.6",
51
+ "react-dom": "19.2.6"
52
+ },
53
+ "peerDependencies": {
54
+ "react": "^19.2.6",
55
+ "react-dom": "^19.2.6"
56
+ }
57
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.