@ticatec/topside-elements 1.2.0 → 1.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.1
4
+
5
+ ### 新增
6
+ - **ListBox 列表内置首尾项(`contentHeader` / `contentFooter` Snippet)**:在 `.listbox-content` 滚动容器内部的最上部与最下部分别新增 `contentHeader` 与 `contentFooter` 插槽。与外部固定不滚动的 `header` / `footer` 不同,这两个插槽的内容位于滚动视口内,跟随列表项一起滚动,适合呈现“全部/快捷选项”、“底部新增”或说明信息。
7
+
3
8
  ## 1.2.0
4
9
 
5
10
  ### 新增
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import {tick, onDestroy, untrack} from "svelte";
2
+ import {tick, onDestroy, untrack, type Snippet} from "svelte";
3
3
  import SearchBox from "../../form/search_box"
4
4
  import type {FilterFn} from "../../types";
5
5
  import type {ListLazyLoader} from "../../types";
@@ -29,9 +29,11 @@
29
29
  title?: string;
30
30
  round?: boolean;
31
31
  filterText?: string;
32
- header?: any;
33
- footer?: any;
34
- loadMoreIndicator?: any;
32
+ header?: Snippet | any;
33
+ footer?: Snippet | any;
34
+ contentHeader?: Snippet | any;
35
+ contentFooter?: Snippet | any;
36
+ loadMoreIndicator?: Snippet | any;
35
37
  }
36
38
 
37
39
  let {
@@ -54,6 +56,8 @@
54
56
  filterText,
55
57
  header,
56
58
  footer,
59
+ contentHeader,
60
+ contentFooter,
57
61
  loadMoreIndicator
58
62
  }: Props = $props();
59
63
 
@@ -293,6 +297,9 @@
293
297
  {/if}
294
298
  <div class="listbox-content" class:selectable={selectMode==='single'} bind:this={scrollElement} onscroll={handleScroll}
295
299
  role="listbox" aria-multiselectable={selectMode === 'multiple' ? true : undefined}>
300
+ {#if contentHeader}
301
+ {@render contentHeader()}
302
+ {/if}
296
303
  {#if filteredList && ItemRender}
297
304
  {#each filteredList as item}
298
305
  {#if selectMode === "multiple"}
@@ -319,6 +326,9 @@
319
326
  {#if hasMore && loadMoreIndicator}
320
327
  {@render loadMoreIndicator()}
321
328
  {/if}
329
+ {#if contentFooter}
330
+ {@render contentFooter()}
331
+ {/if}
322
332
  </div>
323
333
  {#if footer}
324
334
  <div class="box-footer flex-container">
@@ -1,3 +1,4 @@
1
+ import { type Snippet } from "svelte";
1
2
  import type { FilterFn } from "../../types";
2
3
  import type { ListLazyLoader } from "../../types";
3
4
  type OnSelectChange = (item: any) => void;
@@ -22,9 +23,11 @@ interface Props {
22
23
  title?: string;
23
24
  round?: boolean;
24
25
  filterText?: string;
25
- header?: any;
26
- footer?: any;
27
- loadMoreIndicator?: any;
26
+ header?: Snippet | any;
27
+ footer?: Snippet | any;
28
+ contentHeader?: Snippet | any;
29
+ contentFooter?: Snippet | any;
30
+ loadMoreIndicator?: Snippet | any;
28
31
  }
29
32
  declare const ListBox: import("svelte").Component<Props, {}, "selectedItems">;
30
33
  type ListBox = ReturnType<typeof ListBox>;
@@ -4,7 +4,7 @@
4
4
 
5
5
  A list component with optional header / footer snippets, built-in search, lazy loading, and single / multiple selection modes.
6
6
 
7
- > Svelte 5 component. Custom header/footer/load-more content is passed as **Snippets** (`header`, `footer`, `loadMoreIndicator`).
7
+ > Svelte 5 component. Custom header/footer/load-more/content snippets are passed as **Snippets** (`header`, `footer`, `contentHeader`, `contentFooter`, `loadMoreIndicator`).
8
8
 
9
9
  ## Installation
10
10
 
@@ -39,8 +39,10 @@ npm install @ticatec/topside-elements
39
39
  | `round` | `boolean` | `false` | Adds a border radius (`--topside-radius`) |
40
40
  | `class` | `string` | `undefined` | Extra class on the root |
41
41
  | `style` | `string \| null` | `null` | Inline CSS on the root |
42
- | `header` | `Snippet` | `undefined` | Custom header content (overrides `title`) |
43
- | `footer` | `Snippet` | `undefined` | Custom footer content |
42
+ | `header` | `Snippet` | `undefined` | Custom header content (overrides `title`, fixed above content) |
43
+ | `footer` | `Snippet` | `undefined` | Custom footer content (fixed below content) |
44
+ | `contentHeader` | `Snippet` | `undefined` | Custom snippet at the top inside `listbox-content` (scrolls with list items) |
45
+ | `contentFooter` | `Snippet` | `undefined` | Custom snippet at the bottom inside `listbox-content` (scrolls with list items) |
44
46
  | `loadMoreIndicator` | `Snippet` | `undefined` | Custom "loading more" indicator shown at the bottom while `hasMore` |
45
47
  | `onchange` | `(item: any) => void` | `undefined` | Single-mode: fires when the selected item changes (also fires with `null` when filter resets selection) |
46
48
  | `onItemDblClick` | `(item: any) => void` | `undefined` | Single-mode only |
@@ -111,6 +113,26 @@ interface LoadResult {
111
113
  <button disabled={selected.length === 0} onclick={() => console.log(selected)}>OK</button>
112
114
  ```
113
115
 
116
+ ### Scrolling content header & footer (`contentHeader` & `contentFooter`)
117
+
118
+ Unlike `header` and `footer` which remain pinned outside the scroll viewport, `contentHeader` and `contentFooter` sit inside `.listbox-content` at the very top and bottom, scrolling alongside the list items:
119
+
120
+ ```svelte
121
+ <ListBox list={users} itemRender={UserItem} selectMode="single" style="height: 300px;">
122
+ {#snippet contentHeader()}
123
+ <div style="padding: 8px 12px; background: #eef2ff; border-bottom: 1px solid #e0e7ff; cursor: pointer;">
124
+ All Users / Quick Actions (scrolls with list)
125
+ </div>
126
+ {/snippet}
127
+
128
+ {#snippet contentFooter()}
129
+ <div style="padding: 8px 12px; text-align: center; color: #64748b; border-top: 1px solid #f1f5f9;">
130
+ Bottom action or footer notice (scrolls with list)
131
+ </div>
132
+ {/snippet}
133
+ </ListBox>
134
+ ```
135
+
114
136
  ### Lazy-loaded list with custom footer
115
137
 
116
138
  ```svelte
@@ -4,7 +4,7 @@
4
4
 
5
5
  列表组件,可选 header / footer snippet、内置搜索框、懒加载、单选 / 多选。
6
6
 
7
- > Svelte 5 组件。header / footer / 加载更多 通过 **Snippet** 传入(`header`、`footer`、`loadMoreIndicator`)。
7
+ > Svelte 5 组件。header / footer / contentHeader / contentFooter / 加载更多 通过 **Snippet** 传入(`header`、`footer`、`contentHeader`、`contentFooter`、`loadMoreIndicator`)。
8
8
 
9
9
  ## 安装
10
10
 
@@ -39,8 +39,10 @@ npm install @ticatec/topside-elements
39
39
  | `round` | `boolean` | `false` | 加圆角(`--topside-radius`) |
40
40
  | `class` | `string` | `undefined` | 根节点附加 class |
41
41
  | `style` | `string \| null` | `null` | 根节点内联 CSS |
42
- | `header` | `Snippet` | `undefined` | 自定义 header(覆盖 `title`) |
43
- | `footer` | `Snippet` | `undefined` | 自定义 footer |
42
+ | `header` | `Snippet` | `undefined` | 自定义 header(覆盖 `title`,固定在顶部不随列表滚动) |
43
+ | `footer` | `Snippet` | `undefined` | 自定义 footer(固定在底部不随列表滚动) |
44
+ | `contentHeader` | `Snippet` | `undefined` | 位于 `listbox-content` 最上部的自定义组件/片段(跟随列表滚动) |
45
+ | `contentFooter` | `Snippet` | `undefined` | 位于 `listbox-content` 最下部的自定义组件/片段(跟随列表滚动) |
44
46
  | `loadMoreIndicator` | `Snippet` | `undefined` | 自定义"加载更多"指示器,`hasMore` 时显示在底部 |
45
47
  | `onchange` | `(item: any) => void` | `undefined` | 单选模式:选中变化时触发(过滤重置时也会以 `null` 触发一次) |
46
48
  | `onItemDblClick` | `(item: any) => void` | `undefined` | 仅单选模式 |
@@ -111,6 +113,26 @@ interface LoadResult {
111
113
  <button disabled={selected.length === 0} onclick={() => console.log(selected)}>OK</button>
112
114
  ```
113
115
 
116
+ ### 随列表滚动的内置首尾项 (`contentHeader` & `contentFooter`)
117
+
118
+ 与 `header` 和 `footer`(固定在滚动容器外部、不随内容滚动)不同,`contentHeader` 与 `contentFooter` 位于 `.listbox-content` 滚动容器内部的最上部与最下部,跟随列表项一起滚动,适合放置“全部选项”、“快捷动作”或底部的“新增选项”等条目:
119
+
120
+ ```svelte
121
+ <ListBox list={users} itemRender={UserItem} selectMode="single" style="height: 300px;">
122
+ {#snippet contentHeader()}
123
+ <div style="padding: 8px 12px; background: #eef2ff; border-bottom: 1px solid #e0e7ff; cursor: pointer;">
124
+ 全部选项 / 快捷操作(跟随列表滚动)
125
+ </div>
126
+ {/snippet}
127
+
128
+ {#snippet contentFooter()}
129
+ <div style="padding: 8px 12px; text-align: center; color: #64748b; border-top: 1px solid #f1f5f9;">
130
+ 底部操作或说明(跟随列表滚动)
131
+ </div>
132
+ {/snippet}
133
+ </ListBox>
134
+ ```
135
+
114
136
  ### 懒加载 + 自定义 footer
115
137
 
116
138
  ```svelte
package/docs/NAMING.md CHANGED
@@ -342,7 +342,7 @@ interface Action<T = any> {
342
342
  **Events (notifications)**: `onchange` `onclick` `ondblclick` `onfocus` `onblur` `oninput` `onclose` `onselect` `ondelete` `onremove` `onrefresh` `onconfirm` `onaction` `ondownload` `onretry` `onkeydown` `onkeyup` `onkeypress` `oncontextmenu` `ontoggle` `onItemClick` `onRowClick` `onIconClick` `onPageSizeChange` `onFileUploaded` `onFileRejected` `onUploadError` `onPreview` `onResizeEnd`; between DataTable's internal panels: `onCellClick` `onWidthChange` `onRowExpand` `onRowSelectChange` `onToggleSelectAll`
343
343
  **Hooks (veto)**: `beforeClose` `beforeRemove` `beforeChange` `beforeTransfer`
344
344
  **Instance methods**: `focus()` `blur()` `clear()` `open()` `close()` `reset()` `push()` `pop()` `getElement()` `openFileDialog()`
345
- **Snippets**: `children` `header` `headerExtra` `footer` `left` `right` `top` `bottom` `sidebar` `home` `leadingIcon` `trailingIcon` `popup` `item` `tab` `node` `chevronIcon` `nodeIcon` `from` `to`
345
+ **Snippets**: `children` `header` `headerExtra` `footer` `contentHeader` `contentFooter` `left` `right` `top` `bottom` `sidebar` `home` `leadingIcon` `trailingIcon` `popup` `item` `tab` `node` `chevronIcon` `nodeIcon` `from` `to`
346
346
 
347
347
  ---
348
348
 
package/docs/NAMING_CN.md CHANGED
@@ -342,7 +342,7 @@ interface Action<T = any> {
342
342
  **事件(通知)**:`onchange` `onclick` `ondblclick` `onfocus` `onblur` `oninput` `onclose` `onselect` `ondelete` `onremove` `onrefresh` `onconfirm` `onaction` `ondownload` `onretry` `onkeydown` `onkeyup` `onkeypress` `oncontextmenu` `ontoggle` `onItemClick` `onRowClick` `onIconClick` `onPageSizeChange` `onFileUploaded` `onFileRejected` `onUploadError` `onPreview` `onResizeEnd`;DataTable 内部面板间:`onCellClick` `onWidthChange` `onRowExpand` `onRowSelectChange` `onToggleSelectAll`
343
343
  **钩子(否决)**:`beforeClose` `beforeRemove` `beforeChange` `beforeTransfer`
344
344
  **实例方法**:`focus()` `blur()` `clear()` `open()` `close()` `reset()` `push()` `pop()` `getElement()` `openFileDialog()`
345
- **Snippet**:`children` `header` `headerExtra` `footer` `left` `right` `top` `bottom` `sidebar` `home` `leadingIcon` `trailingIcon` `popup` `item` `tab` `node` `chevronIcon` `nodeIcon` `from` `to`
345
+ **Snippet**:`children` `header` `headerExtra` `footer` `contentHeader` `contentFooter` `left` `right` `top` `bottom` `sidebar` `home` `leadingIcon` `trailingIcon` `popup` `item` `tab` `node` `chevronIcon` `nodeIcon` `from` `to`
346
346
 
347
347
  ---
348
348
 
@@ -40,6 +40,8 @@ import ListBox from '@ticatec/topside-elements/ListBox';
40
40
  | `filterText` | 是 | `string` | 否 | `undefined` | 否 | 过滤输入框的外部初始值或受控值,用于预设搜索条件。 |
41
41
  | `header` | 否 | `any` | 否 | `undefined` | 否 | 可选配置,具体取值范围和数据结构见类型列。 |
42
42
  | `footer` | 否 | `any` | 否 | `undefined` | 否 | 可选配置,具体取值范围和数据结构见类型列。 |
43
+ | `contentHeader` | 否 | `Snippet \| any` | 否 | `undefined` | 否 | 位于 listbox-content 最上部的自定义组件/片段(跟随列表滚动)。 |
44
+ | `contentFooter` | 否 | `Snippet \| any` | 否 | `undefined` | 否 | 位于 listbox-content 最下部的自定义组件/片段(跟随列表滚动)。 |
43
45
  | `loadMoreIndicator` | 否 | `any` | 否 | `undefined` | 否 | 可选配置,具体取值范围和数据结构见类型列。 |
44
46
 
45
47
  > 组件的“可绑定”表示源码使用了 Svelte 5 的 `$bindable`;服务的“响应式”表示成员使用了 `$state`。复杂类型请同时参考 TypeScript 自动补全。
@@ -121,6 +123,22 @@ import ListBox from '@ticatec/topside-elements/ListBox';
121
123
  - 默认值:`undefined`
122
124
  - 示例写法:`filterText="研发"`
123
125
 
126
+ ### `contentHeader`
127
+
128
+ 位于 `listbox-content` 滚动容器内部的最上部,在所有列表项之前渲染,**跟随列表一起滚动**(与固定的 `header` 区分)。可用于放置如“全部选项”、“快捷搜索”等类似选择项的内容。
129
+
130
+ - 类型:`Snippet | any`
131
+ - 默认值:`undefined`
132
+ - 示例写法:`{#snippet contentHeader()}<div>全部选项</div>{/snippet}`
133
+
134
+ ### `contentFooter`
135
+
136
+ 位于 `listbox-content` 滚动容器内部的最下部,在所有列表项(及加载更多指示器)之后渲染,**跟随列表一起滚动**(与固定的 `footer` 区分)。可用于放置如“新增选项”、“列表说明”等类似选择项的内容。
137
+
138
+ - 类型:`Snippet | any`
139
+ - 默认值:`undefined`
140
+ - 示例写法:`{#snippet contentFooter()}<div>新增选项</div>{/snippet}`
141
+
124
142
  ## 相关类型定义
125
143
 
126
144
  以下定义帮助理解复杂属性的数据结构;其中部分辅助类型属于内部实现,不一定是独立导出入口。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticatec/topside-elements",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "A comprehensive UI component library for Svelte applications with rich form controls, data tables, layouts and interactive elements",
5
5
  "keywords": [
6
6
  "svelte",