rj-grid 0.2.1 → 0.2.2

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/dist/style.css CHANGED
@@ -261,6 +261,111 @@
261
261
  padding: 2px;
262
262
  }
263
263
 
264
+ .rj-query-select.rj-opt-select {
265
+ position: relative;
266
+ display: inline-flex;
267
+ min-width: 120px;
268
+ font-size: var(--rj-ui-font, 12px);
269
+ }
270
+
271
+ .rj-opt-trigger {
272
+ display: inline-flex;
273
+ flex: 1;
274
+ gap: 4px;
275
+ align-items: center;
276
+ justify-content: space-between;
277
+ width: 100%;
278
+ height: calc(var(--rj-ui-h, 26px) - 2px);
279
+ padding: 0 6px;
280
+ font-size: var(--rj-ui-font, 12px);
281
+ color: var(--rj-text);
282
+ cursor: pointer;
283
+ background: var(--rj-bg);
284
+ border: 1px solid var(--rj-border-strong);
285
+ border-radius: var(--rj-radius);
286
+ outline: none;
287
+ }
288
+ .rj-opt-trigger:focus, .rj-opt-trigger:hover {
289
+ border-color: var(--rj-primary);
290
+ }
291
+ .rj-opt-trigger.is-placeholder .rj-opt-text {
292
+ color: var(--rj-text-secondary);
293
+ }
294
+
295
+ .rj-opt-text {
296
+ overflow: hidden;
297
+ text-overflow: ellipsis;
298
+ white-space: nowrap;
299
+ }
300
+
301
+ .rj-opt-arrow {
302
+ flex: none;
303
+ color: var(--rj-text-secondary);
304
+ }
305
+
306
+ .rj-opt-panel {
307
+ position: absolute;
308
+ top: 100%;
309
+ left: 0;
310
+ z-index: 60;
311
+ display: flex;
312
+ flex-direction: column;
313
+ min-width: 100%;
314
+ max-width: 320px;
315
+ margin-top: 2px;
316
+ background: var(--rj-bg);
317
+ border: 1px solid var(--rj-border);
318
+ border-radius: var(--rj-radius);
319
+ box-shadow: var(--rj-shadow);
320
+ }
321
+
322
+ .rj-opt-search {
323
+ width: calc(100% - 8px);
324
+ height: calc(var(--rj-ui-h, 26px) - 2px);
325
+ padding: 0 6px;
326
+ margin: 4px;
327
+ font-size: var(--rj-ui-font, 12px);
328
+ color: var(--rj-text);
329
+ background: var(--rj-bg);
330
+ border: 1px solid var(--rj-border-strong);
331
+ border-radius: var(--rj-radius);
332
+ outline: none;
333
+ }
334
+ .rj-opt-search:focus {
335
+ border-color: var(--rj-primary);
336
+ }
337
+
338
+ .rj-opt-list {
339
+ max-height: 220px;
340
+ overflow: auto;
341
+ }
342
+
343
+ .rj-opt-row {
344
+ display: flex;
345
+ gap: 4px;
346
+ align-items: center;
347
+ padding: 4px 8px;
348
+ line-height: 1.5;
349
+ cursor: pointer;
350
+ }
351
+ .rj-opt-row:hover, .rj-opt-row.is-active {
352
+ color: var(--rj-primary);
353
+ background: var(--rj-primary-bg);
354
+ }
355
+ .rj-opt-row.is-selected .rj-option-label {
356
+ font-weight: 600;
357
+ }
358
+
359
+ .rj-opt-check {
360
+ flex: none;
361
+ margin: 0;
362
+ }
363
+
364
+ .rj-opt-empty {
365
+ padding: 6px 8px;
366
+ color: #999;
367
+ }
368
+
264
369
  .rj-query-add {
265
370
  border-style: dashed;
266
371
  }
@@ -1139,6 +1244,27 @@
1139
1244
  color: var(--rj-primary);
1140
1245
  }
1141
1246
 
1247
+ .rj-option-tree .rj-option-row {
1248
+ display: flex;
1249
+ gap: 4px;
1250
+ align-items: center;
1251
+ }
1252
+ .rj-option-tree .rj-option-caret {
1253
+ flex: none;
1254
+ width: 14px;
1255
+ color: var(--rj-text-secondary);
1256
+ cursor: pointer;
1257
+ user-select: none;
1258
+ }
1259
+ .rj-option-tree .rj-option-caret.is-leaf {
1260
+ cursor: default;
1261
+ }
1262
+ .rj-option-tree .rj-option-label {
1263
+ overflow: hidden;
1264
+ text-overflow: ellipsis;
1265
+ white-space: nowrap;
1266
+ }
1267
+
1142
1268
  .rj-editor-error {
1143
1269
  position: absolute;
1144
1270
  top: 100%;
@@ -0,0 +1,49 @@
1
+ import type { RjEditorOption } from './types';
2
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
3
+ options?: RjEditorOption[] | undefined;
4
+ modelValue?: any;
5
+ multiple?: boolean | undefined;
6
+ placeholder?: string | undefined;
7
+ }>, {
8
+ options: () => never[];
9
+ modelValue: undefined;
10
+ multiple: boolean;
11
+ placeholder: string;
12
+ }>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
13
+ "update:modelValue": (v: any) => void;
14
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
15
+ options?: RjEditorOption[] | undefined;
16
+ modelValue?: any;
17
+ multiple?: boolean | undefined;
18
+ placeholder?: string | undefined;
19
+ }>, {
20
+ options: () => never[];
21
+ modelValue: undefined;
22
+ multiple: boolean;
23
+ placeholder: string;
24
+ }>>> & Readonly<{
25
+ "onUpdate:modelValue"?: ((v: any) => any) | undefined;
26
+ }>, {
27
+ options: RjEditorOption[];
28
+ placeholder: string;
29
+ modelValue: any;
30
+ multiple: boolean;
31
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
32
+ export default _default;
33
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
34
+ type __VLS_TypePropsToRuntimeProps<T> = {
35
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
36
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
37
+ } : {
38
+ type: import('vue').PropType<T[K]>;
39
+ required: true;
40
+ };
41
+ };
42
+ type __VLS_WithDefaults<P, D> = {
43
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
44
+ default: D[K];
45
+ }> : P[K];
46
+ };
47
+ type __VLS_Prettify<T> = {
48
+ [K in keyof T]: T[K];
49
+ } & {};
@@ -22,9 +22,32 @@ export declare const defaultOptionsAccessor: RjOptionsAccessor;
22
22
  * 把任意接口返回归一成 RjEditorOption[]:
23
23
  * - map 命中优先(完全自定义);
24
24
  * - 否则按 labelKey/valueKey(或默认字段)取;
25
- * - childrenKey(默认 'children')命中数组即递归拍平(depth 缩进不写进 label,保持干净 value→label 表)。
25
+ * - childrenKey(默认 'children')命中数组即保留为 children,递归归一(不再拍平),供下拉按层级渲染。
26
26
  */
27
27
  export declare function normalizeOptions(raw: unknown, shape?: RjOptionShape): RjEditorOption[];
28
+ /** 深度优先拍平选项树(丢弃 children 引用),供 value→label 映射 / 枚举候选等需要扁平列表的消费点 */
29
+ export declare function flattenOptions(options: RjEditorOption[]): RjEditorOption[];
30
+ /**
31
+ * 按搜索词剪枝选项树(大小写不敏 contains):
32
+ * - 节点自身命中 → 保留该节点及其完整子树(可继续下钻);
33
+ * - 自身未命中但有后代命中 → 作为祖先路径保留(children 为剪枝后的子集);
34
+ * - 空查询原样返回。返回全新节点对象,不污染缓存。
35
+ */
36
+ export declare function filterOptionTree(options: RjEditorOption[], query: string): RjEditorOption[];
37
+ /** 树渲染行:option + 层级深度 + 是否可展开 + 当前是否已展开 */
38
+ export interface RjOptionRow {
39
+ option: RjEditorOption;
40
+ depth: number;
41
+ hasChildren: boolean;
42
+ expanded: boolean;
43
+ }
44
+ /**
45
+ * 按展开集合把(已剪枝的)选项树铺成可渲染的可见行(深度优先)。
46
+ * expanded 以 String(value) 为键;未展开节点的子树不进入可见行。
47
+ */
48
+ export declare function flattenTreeForRender(options: RjEditorOption[], expanded: Set<string>): RjOptionRow[];
49
+ /** 收集树中所有“有子节点”的 value(String 化),用于默认展开全部 */
50
+ export declare function collectParentKeys(options: RjEditorOption[], acc?: Set<string>): Set<string>;
28
51
  /** 解析选项源所需的网格级加载器 */
29
52
  export interface RjOptionLoaders {
30
53
  dictLoader?: (key: string) => unknown | Promise<unknown>;
@@ -108,11 +108,14 @@ export type RjEditorType = 'input' | 'number' | 'date' | 'select' | 'richSelect'
108
108
  export interface RjEditorOption {
109
109
  label: string;
110
110
  value: any;
111
+ /** 树形子节点:载体源含 childrenKey 时保留层级(下拉按树渲染,显示/标签映射自动拍平) */
112
+ children?: RjEditorOption[];
111
113
  }
112
114
  /**
113
115
  * 统一选项载体:一份数据源同时驱动 显示(value→label) / select 筛选候选 / select 编辑器 / NLQ 枚举。
114
116
  * 数组=静态候选;函数=工厂(可同步/异步,网格级按列只解析一次);对象=按 load/ref/dict 取数,
115
- * 再用 map 或 labelKey/valueKey 归一,childrenKey(默认 'children')命中即递归拍平树(label 不加缩进)。
117
+ * 再用 map 或 labelKey/valueKey 归一,childrenKey(默认 'children')命中数组即保留为 children 树,
118
+ * 供下拉按层级渲染(显示标签映射会自动深度优先拍平,父/子节点均可命中 value→label)。
116
119
  */
117
120
  export type RjOptionSource = RjEditorOption[] | ((row?: RjRowData) => RjEditorOption[] | Promise<RjEditorOption[]>) | {
118
121
  /** 静态候选(对象式) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rj-grid",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "零第三方依赖的自研 Vue3 虚拟表格:虚拟滚动 / 冻结列 / 行拖拽 / 分组透视 / 公式 / SSRM / 主题 i18n / 自然语言查询",
5
5
  "type": "module",
6
6
  "license": "MIT",