@keenaioc/data-view 0.2.0-alpha.11 → 0.2.0-alpha.14

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/INTEGRATION.md +85 -0
  3. package/KNOWN-LIMITATIONS.md +19 -0
  4. package/README.md +4 -2
  5. package/dist/action-menu.d.ts +37 -0
  6. package/dist/action-menu.d.ts.map +1 -0
  7. package/dist/action-menu.js +64 -0
  8. package/dist/action-menu.js.map +1 -0
  9. package/dist/column-menu.d.ts +2 -16
  10. package/dist/column-menu.d.ts.map +1 -1
  11. package/dist/column-menu.js +5 -62
  12. package/dist/column-menu.js.map +1 -1
  13. package/dist/data-view.d.ts.map +1 -1
  14. package/dist/data-view.js +140 -24
  15. package/dist/data-view.js.map +1 -1
  16. package/dist/dialog.d.ts +8 -0
  17. package/dist/dialog.d.ts.map +1 -0
  18. package/dist/dialog.js +10 -0
  19. package/dist/dialog.js.map +1 -0
  20. package/dist/gantt-grid.d.ts +2 -1
  21. package/dist/gantt-grid.d.ts.map +1 -1
  22. package/dist/gantt-grid.js +3 -3
  23. package/dist/gantt-grid.js.map +1 -1
  24. package/dist/index.d.ts +1 -1
  25. package/dist/index.js +1 -1
  26. package/dist/registry.d.ts +1 -4
  27. package/dist/registry.d.ts.map +1 -1
  28. package/dist/registry.js +1 -17
  29. package/dist/registry.js.map +1 -1
  30. package/dist/relation-picker.d.ts +21 -0
  31. package/dist/relation-picker.d.ts.map +1 -0
  32. package/dist/relation-picker.js +84 -0
  33. package/dist/relation-picker.js.map +1 -0
  34. package/dist/row-actions.d.ts +11 -0
  35. package/dist/row-actions.d.ts.map +1 -0
  36. package/dist/row-actions.js +15 -0
  37. package/dist/row-actions.js.map +1 -0
  38. package/dist/schedule-view.d.ts +2 -1
  39. package/dist/schedule-view.d.ts.map +1 -1
  40. package/dist/schedule-view.js +2 -2
  41. package/dist/schedule-view.js.map +1 -1
  42. package/dist/style.css +29 -3
  43. package/dist/types.d.ts +26 -2
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/v2-panels.d.ts +1 -8
  46. package/dist/v2-panels.d.ts.map +1 -1
  47. package/dist/v2-panels.js +2 -7
  48. package/dist/v2-panels.js.map +1 -1
  49. package/dist/view-workspace.js +2 -2
  50. package/dist/view-workspace.js.map +1 -1
  51. package/package.json +5 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,34 @@
2
2
 
3
3
  歷史紀錄保留當時版本資訊;部分舊版已下架,歷史安裝/回退指令不代表仍可下載。alpha.8 的回退基準為 alpha.7。
4
4
 
5
+ ## 0.2.0-alpha.14 — 2026-09-08(Alpha)
6
+
7
+ - 新增:資料列右鍵選單,提供在上方/下方新增一筆、確認刪除此筆;保留可讀名稱的 ⋯ 按鈕及 Shift+F10/選單鍵入口。桌面、卡片與甘特左表可操作,不劫持輸入框、連結及自訂動作的原生選單。只操作目標永久 row ID,不擴大到其他已選列。
8
+ - 介面:新增可選 `onRowChange`、`permissions.canChangeRow(row, action)`、`features.rowMenu` 與公開 `RowChange`/`RowChangeAction` 型別。必須接 callback 並明確授權;host 負責新 ID、預設值、相對順序、刪除政策、原子保存及重新提供 rows。回呼附上 query/groupPath,不自行改資料或排序。
9
+ - 刪除:二次確認預設聚焦取消,保存中防止重複提交;失敗/衝突保留確認與重試。新增不清除既有儲存格歷史;成功刪除只移除涉及該列或依赖該列排程 read-set 的整筆紀錄,保留其他紀錄,不拆分原子批次。新增/刪除本身不加入儲存格復原。
10
+ - 改善:整個欄位標題成為可點擊的選單按鈕,移除右側下拉符號與其占位,保留完整標題提示、鍵盤、拖曳排序及獨立欄寬把手。
11
+ - 改善:預設附件欄空值留白,非空僅顯示 `+N` 總數;點開才顯示既有檔案連結與新增附件。空白可編輯格仍可點入上傳,唯讀及自訂 renderer/Editor/quick view 保留。
12
+ - 相容:包含 alpha.13 可讀輔助名稱與單次 history: skip 介面;無必填 prop 或 ViewConfig/資料遷移。未接 row callback 的專案不出現列操作;表頭/附件顯示改動會隨套件與同版 CSS 生效。
13
+ - 升級:`npm install --save-exact @keenaioc/data-view@0.2.0-alpha.14`,提交 dependency/lockfile 並使用同版本 CSS。新增刪除需 host 接入,不會單靠升級就取得資料庫寫入權限。回退還原原精確版本與 lockfile 並移除列操作接入;若回到 alpha.12,亦需撤回依賴 history: skip 的策略。
14
+ - 驗收:程式與 React 元件測試涵蓋目標 ID、上下新增、確認取消、權限變更、失敗/重試、重複提交、其他列歷史、表頭入口與附件上傳。實際瀏覽器/真機/讀屏軟體及 host 保存/重新載入仍待接入端驗收。
15
+
16
+ ## 0.2.0-alpha.13 — 2026-09-08(候選,功能併入 alpha.14)
17
+
18
+ - 修正:儲存格、勾選按鈕與甘特左表詳情按鈕的輔助名稱沿用可讀資料名稱,不再插入內部 row ID。保留既有讀取權限、友善空值替代文字;選取、寫入與復原仍使用永久 ID。
19
+ - 新增:公開 `BatchCommitResult`;`onBatchCommit` 成功時可回傳 `{ history: "skip" }`,只略過本次完整操作的儲存格復原紀錄,保留既有 undo/redo 堆疊。未回傳或 `history: "record"` 保持原行為。undo/redo 重播忽略此選項,仍正常移轉歷史。
20
+ - 邊界:不跳過權限、驗證、寫入或衝突檢查;失敗不改歷史。略過操作若改過舊紀錄的同一格,之後復原仍可能因原值不同而衝突,不會自動改寫舊紀錄。批次整筆適用,不支援挑格略過。
21
+ - 相容:無新增必要 props、ViewConfig 或資料遷移。既有回傳 void/Promise<void> 的 callbacks 保持相容;同時提供 onCellCommit 時,單格仍優先走原本不記錄歷史的路徑。
22
+ - 升級:`npm install --save-exact @keenaioc/data-view@0.2.0-alpha.13`,提交 dependency/lockfile,沿用同版本 CSS。需略過紀錄的 host 接入回傳值;其他接入端無需修改。回退 alpha.12 dependency/lockfile 並移除新回傳策略;alpha.12 不會辨識 skip。
23
+ - 驗收:程式驗證與 SSR 覆蓋可讀名稱及歷史保留;實際瀏覽器、輔助科技及 host 保存/重載仍由接入端驗收。
24
+
25
+ ## 0.2.0-alpha.12 — 2026-09-07(Alpha)
26
+
27
+ - 新增:關聯儲存格改用可搜尋的選擇視窗,開啟即顯示搜尋框,可依選項名稱/名稱中的編號篩選,忽略大小寫、全形差異與前後空白,多個關鍵字取交集。保留目前關聯、清除、無結果提示與長清單捲動;同名項目仍按永久 ID 辨識。
28
+ - 相容:不新增必要 props 或 ViewConfig;沿用 field.options 及既有單格/批次寫入、權限、失敗/衝突提示。桌面、甘特左表、手機與詳情中的預設關聯入口共用。自訂 Editor/render/renderQuickView 保留。
29
+ - 邊界:只搜尋 host 已提供的授權選項,不自行讀取整張關聯表或發起遠端查詢;目前關聯未在清單仍保留名稱,不因搜尋/關閉而清空。UI 保持單一關聯,不新增多選或關聯表格欄位瀏覽器。
30
+ - 升級:`npm install --save-exact @keenaioc/data-view@0.2.0-alpha.12`,提交 dependency/lockfile,載入同版本套件 CSS。無資料遷移;回退還原 alpha.11 dependency/lockfile 並重建,回復原生下拉。
31
+ - 驗收:搜尋與 ID 写入/唯讀/空結果有程式測試,實際瀏覽器與真機焦點、輸入法及捲動仍待接入驗收。
32
+
5
33
  ## 0.2.0-alpha.11 — 2026-09-07(Alpha)
6
34
 
7
35
  - 新增:表格與甘特左表的欄位表頭提供操作選單;滑鼠懸浮/鍵盤聚焦顯示入口,觸控裝置常駐。提供重新命名、複製欄位與值、隱藏、固定、排序、篩選、分組、整體欄位設定及確認刪除。
package/INTEGRATION.md CHANGED
@@ -256,3 +256,88 @@ const nextView = {
256
256
  - 使用原生 Popover 顶層避免固定欄/捲動容器裁切;不支援 Popover 時改用既有原生 dialog。外部點擊、Escape、表格/頁面捲動及尺寸變更會關閉浮動選單;選單本身可捲動。不支援欄位說明、整欄手動填色、通知自動化、左右插入或由此建立看板等額外功能。
257
257
 
258
258
  接入時升級精確 `@keenaioc/data-view@0.2.0-alpha.11` 並載入相同版本 `@keenaioc/data-view/style.css`,不需要 host 覆蓋套件 CSS。驗收長欄名、窄欄、固定欄、橫向/縱向捲動、觸控表格、鍵盤、唯讀權限與結構回呼成功/失敗/衝突。程式與 SSR 檢查不等同瀏覽器實測。
259
+
260
+
261
+ ## alpha.12 關聯搜尋
262
+
263
+ 預設可編輯關聯儲存格點開後顯示搜尋視窗,搜尋框自動聚焦。依 `field.options[].label` 的名稱或其中的編號搜尋,大小寫、全形差異及前後空白會正規化;多個空白分隔關鍵字必須都出現在名稱。搜尋不比對隱藏 ID,也不觸發任何寫入。選定項目沿用 `{id: option.value, label: option.label}`;清除沿用 null,取消或關閉保留原關聯,重新選同一 ID 不重複送出。相同名稱仍為不同 ID 的獨立選項。
264
+
265
+ 目前關聯不在選項中時,顯示原名稱並提示不在清單,不以原始 ID 作主要名稱,也不自動改關聯。Host 仍需提供經授權的 options;套件僅搜尋這份清單,沒有遠端搜尋 callback、分頁載入或自動讀取關聯表。編號若要搜尋,需包含在 option.label。這次不增加關聯資料表欄位瀏覽器或多選關聯。
266
+
267
+ 桌面/甘特/手機/詳情的預設關聯入口共用;自訂 render、Editor、renderQuickView 維持原專案能力。原本 ReferenceEditor 的搜尋介面仍保留。表格 Enter/F2 可開啟預設視窗;搜尋框向下鍵移至結果,結果用上下/Home/End 移動、Enter/Space 選擇、Escape 取消,Tab 使用原生焦點路徑。視窗鍵盤、複製貼上不傳給底層儲存格快捷鍵。原生 dialog 避免被虛擬儲存格及固定欄裁切。
268
+
269
+ 沿用既有 onCellCommit/onBatchCommit、權限與儲存提示,不新增 props/ViewConfig 或資料遷移。升級精確 alpha.12 並同步套件 CSS;需驗收輸入法、長清單、同名、缺席關聯、唯讀、保存失敗/衝突與重載。程式及 SSR 通過不代表實際瀏覽器互動已完成驗收。
270
+
271
+
272
+ ## alpha.13 可讀輔助名稱與單次略過復原
273
+
274
+ 儲存格、勾選按鈕、甘特左表詳情按鈕共用既有可讀列名稱:優先採用 `getRowLabel(row)`,否則依目前視圖標題/手機摘要欄位與 formatter 取值,再用「未命名工作」替代空白;標題欄位不可讀時顯示「無權限」。Host 的 getRowLabel 必須只回傳有權讀取的名稱,勿回傳 UUID。`getRowId` 維持永久 ID,重複名稱不影響選取或寫入。
275
+
276
+ `DataView` 與 `DataViewWorkspace` 的 `onBatchCommit` 均支援可選成功回傳值 `BatchCommitResult`:
277
+
278
+ ```ts
279
+ import type { DataViewProps } from "@keenaioc/data-view";
280
+
281
+ const onBatchCommit: NonNullable<DataViewProps<Row>["onBatchCommit"]> = async (commit) => {
282
+ // 既有 adapter 必須完成授權、原值/版本檢查及整批原子保存。
283
+ await saveAtomicChanges(commit);
284
+ const isNewWrite = commit.reason !== "undo" && commit.reason !== "redo";
285
+ const onlyReferenceChange = commit.changes.every(
286
+ (change) => change.field.id === referenceFieldId,
287
+ );
288
+ if (isNewWrite && onlyReferenceChange) return { history: "skip" };
289
+ // 省略回傳值等同 { history: "record" }。
290
+ };
291
+ ```
292
+
293
+ `Row`、`saveAtomicChanges` 及 `referenceFieldId` 是接入端自己的型別、保存函式與欄位映射。不要把所有 relation 欄位都固定略過;由 host 依本次業務操作決定。
294
+
295
+ - `skip` 在保存成功後才生效,對本次完整操作適用,不新增 undo 紀錄,也不清除既有 undo 或 redo。其他格已存的編輯值保持原狀,其歷史仍可正常復原/重做。下次一般記錄操作仍按原規則清掉 redo,undo 上限仍為 20 筆。
296
+ - 拋出錯誤/拒絕 Promise 時仍提示失敗或衝突,兩個堆疊保持原狀;不要保存失敗卻回傳 skip,skip 不是失敗代碼。
297
+ - `undo`/`redo` 回呼仍須執行真正的反向/正向寫入;即使回傳 skip,成功時仍正常移轉原紀錄,失敗時不移轉。不要將關聯改動偽裝為 undo/redo。
298
+ - 不會重寫或刪除舊紀錄。若略過操作改到舊紀錄同一格,舊紀錄可能因原值不符而衝突;仍保留並提示,禁止為通過復原而忽略版本/原值檢查。多格紀錄不會自動拆成部分復原,排程 read-set/revision 檢查照常。
299
+ - 此介面只管理該 DataView 實例內的儲存格歷史,不代管 host 稽核、草稿、跨頁快取或資料保存。不要為一次關聯更新改 React key/identityKey、切換 callback、重新掛載表格或關閉整體 undo。原有身分/查詢切換、欄位結構及依賴變更清除歷史的規則仍適用。
300
+ - 同時提供 onCellCommit/onBatchCommit 時單格仍優先前者;要讓一般單格編輯記錄歷史而特定單次操作略過,僅提供 onBatchCommit。onCellCommit 的回傳契約不變。
301
+
302
+ 精確升級 `0.2.0-alpha.13`,保留現有 ViewConfig(schemaVersion 1)與套件 CSS,不需資料遷移。回退 alpha.12 前撤回新回傳策略;舊版會把這些操作再次納入歷史。
303
+
304
+
305
+ ## alpha.14 列操作、整欄標題與附件數量
306
+
307
+ DataView 與 DataViewWorkspace 新增可選介面:
308
+
309
+ ```ts
310
+ import type { DataViewProps, RowChange } from "@keenaioc/data-view";
311
+
312
+ const onRowChange = async (request: RowChange<Row>): Promise<void> => {
313
+ // 按永久 rowId 核對最新權限及 row 的版本;不能以畫面列號或名稱寫入。
314
+ if (request.action === "delete") {
315
+ await deleteRecordAtomically(request.rowId, request.row);
316
+ } else {
317
+ await insertRecordRelativeTo({
318
+ anchorId: request.rowId,
319
+ position: request.action === "insertBefore" ? "before" : "after",
320
+ groupPath: request.groupPath,
321
+ query: request.query,
322
+ });
323
+ }
324
+ await reloadRows();
325
+ };
326
+ const rowPermissions: DataViewProps<Row>["permissions"] = {
327
+ canChangeRow: (row, action) => action === "delete"
328
+ ? canDeleteRecord(row)
329
+ : canCreateBesideRecord(row),
330
+ };
331
+ ```
332
+
333
+ 上述 Row、資料服務與授權函式均由 host 實作;套件不產生業務資料、不複製目標列值,不直接連資料庫。`RowChange` 含 `id`(本次操作 ID)、`action: "insertBefore" | "insertAfter" | "delete"`、`rowId`/`row`(插入參考列或刪除目標列)、`groupPath`(永久分組鍵)、`query`。Host 自行生成新資料永久 ID、必填預設值、分組值及排序位置;只有保存成功才 resolve 並提供最新 rows,失敗或衝突須 throw。
334
+
335
+ - 必須同時提供 onRowChange 且 `permissions.canChangeRow(row, action) === true` 才可寫入;普通單格 canEditRow 權限不會自動取得新增/刪除權。後端仍需重查授權與資料版本。`features.rowMenu: false` 可關閉整組入口;未接 callback 不顯示。
336
+ - 桌面與甘特左表右鍵可開啟,卡片另有常駐 ⋯;鍵盤可聚焦 ⋯ 或用 Shift+F10/選單鍵。只處理點到的一筆,不依多選自動批次刪除。文字輸入、連結和自訂動作保留原生右鍵功能。
337
+ - 有排序、篩選、分組或部分遠端資料時,插入位置由 host 依永久參考 ID 與完整資料決定。不得只在已載入陣列用可視列號算全表位置。Host 可保存手動順序/合法分組預設值,或拒絕不支援的插入情境;套件不移除使用者排序、篩選,也不保證新列在排序後仍緊鄰參考列。不可讀分組禁止插入;空表沒有參考列,請用 host 既有全表新增入口。
338
+ - 新增/刪除在既有寫入 queue 的全表屏障執行;等待已排入的寫入後,重新檢查目前列、權限及查詢。刪除前確認,失敗保留對話框可重試;不樂觀刪除。刪除政策(軟刪除、關聯限制、附件與稽核)由 host 控制,核心不處理關聯級聯。
339
+ - 新增保留全部既有儲存格 undo/redo;刪除成功後,只剔除涉及該列的完整歷史項目,以及排程 read-set 依賴該列的項目,其餘紀錄保留。混合多列原子批次會整筆剔除,不能拆出剩餘格假裝可原子復原。列新增/刪除不支援儲存格 undo。
340
+ - 表頭改為整個標題按鈕,無下拉圖示占位;保留 title 完整名稱、鍵盤選單及拖曳/欄寬操作。原 features.columnMenu 與欄位 callback/權限不變;窄到不足以容納文字的欄位仍正常省略,可拖寬。
341
+ - 預設附件儲存格沒有內容即留白,有內容只顯示總數 `+1`、`+2` 等。點空白可編輯格或數量,開啟附件視窗,沿用既有檔案連結及 onRequestAttachment 保存。空白唯讀格不提供入口;有內容唯讀格可查看。自訂 field.render/Editor/renderQuickView 不強制改寫。附件視窗和資料詳情保留檔名,不把數量當永久附件 ID。
342
+
343
+ 精確升級 alpha.14,CSS 必須同版;新介面全為可選,schemaVersion 保持 1。回退還原原套件/lockfile 與 host adapter;無資料或設定遷移。
@@ -61,3 +61,22 @@
61
61
  表頭選單與確認表單已加入程式與 SSR 測試,但本輪沒有完成真實瀏覽器懸浮、焦點、Popover/dialog fallback、固定欄裁切、拖曳干擾及觸控驗收。既有瀏覽器 URL 政策限制仍適用。卡片呈現沒有表頭,使用既有設定入口。
62
62
 
63
63
  重命名/複製/刪除需要 host 開放管理權限並實作 onFieldChange;這些入口不能代替後端欄位管理與資料保存。刪除與複製的真實值處理、交易、稽核與衝突由 host 驗收。表頭快捷篩選一次只編輯此欄第一個條件;完整條件仍在篩選面板。欄位說明、任意整欄填色、通知、自動化、左右插入與建立看板未包含於本次。
64
+
65
+
66
+ ## alpha.12 關聯搜尋
67
+
68
+ 搜尋範圍限 host 提供的授權 options.label;沒有遠端搜尋或自動載入完整關聯資料。清單會捲動但不另做選項虛擬化;本次僅單一關聯,沒有截圖中的關聯表格檢視器。瀏覽器/真機原生 dialog、焦點還原、輸入法、捲動及真實保存/衝突仍待接入驗收。
69
+
70
+
71
+ ## alpha.13 單次復原政策
72
+
73
+ `BatchCommitResult.history: "skip"` 僅略過成功的新操作,保留整個既有 undo/redo;不支援批次內逐格策略、歷史重寫或跨實例/跨查詢保留。略過操作與舊紀錄若涉及同一格,舊紀錄仍可能被原值/排程衝突檢查擋下,不能保證這種相依歷史可重播。Host 應由一開始就一致採用關聯操作政策,並保留正式衝突處理。正式介面不清除其他格紀錄,也不改 host 保存、草稿與稽核。
74
+
75
+ 輔助名稱沿用 host 提供的可讀名稱與權限;套件不能把 host 傳入的 UUID 或不可讀文字自動轉成業務名稱。本輪不宣稱實際讀屏軟體、瀏覽器或接入端保存/重載已驗收。
76
+
77
+
78
+ ## alpha.14 列操作與簡化顯示
79
+
80
+ 列新增/刪除需要 host 的 onRowChange 及明確 canChangeRow 授權;套件不代管新 ID、必填欄位、相對順序、關聯級聯、軟刪除與保存。排序/篩選可能讓新列出现在別處或不出現,部分遠端清單不能當完整排序來源。空表沒有相對插入參考列。只有單筆確認刪除,沒有右鍵批次新增、批次刪除或列復原;涉及已刪除列的原子儲存格歷史整筆剔除,其他歷史保留。
81
+
82
+ 表頭取消箭頭占位,但不自動改欄寬;很窄的欄位仍可能省略文字。附件計數只套用預設儲存格,不覆蓋自訂 renderer/Editor/quick view;點開視窗後仍需檔名與連結以辨識附件。原生 popover/dialog 的瀏覽器、真機與讀屏行為,以及真實 adapter 的新增/刪除/上傳與重載,仍待接入驗收。
package/README.md CHANGED
@@ -4,14 +4,14 @@ HomeYa 共用資料視圖引擎。以 既有工作台的既有表格成果為主
4
4
 
5
5
  套件不包含資料庫、業務流程、報價公式、使用者帳號或專案資料。接入專案透過 `DataView` 的 callbacks 處理讀取、寫入、附件、權限與稽核。
6
6
 
7
- 本文件版本:**`0.2.0-alpha.11`(公開 Alpha 測試版)**。新增欄位表頭操作選單與分組自訂順序;保留電腦/手機各自設定及既有欄位移動。程式、型別、建置及打包檢查已通過;修正後瀏覽器操作驗收尚未完成,接入時須重測。
7
+ 本文件版本:**`0.2.0-alpha.14`(公開 Alpha 測試版)**。新增列右鍵操作、整個欄位標題開啟選單及附件 `+N` 計數顯示;保留可讀輔助名稱與 `onBatchCommit` 成功回傳 `{ history: "skip" }` 的單次復原紀錄政策,保留其他格的既有復原/重做;DataViewWorkspace 同樣支援。保留關聯搜尋、欄位表頭選單、分組自訂順序及電腦/手機各自設定。程式、型別、建置及打包檢查已通過;修正後瀏覽器操作驗收尚未完成,接入時須重測。
8
8
 
9
9
  既有基底:整合 T01~T19:工作台密度與 renderer、權限及狀態分離、資料列拖曳、並行寫入、手機獨立版面、排程空值、無分頁與遠端查詢契約。原先規劃的 alpha.6/alpha.7 合併為本版;alpha.6 未另行發布。
10
10
 
11
11
  本版保留 Alpha 限制:自動測試與建置通過,完整桌機/手機操作驗收尚未完成。先在測試專案接入,再決定是否升級正式系統。
12
12
 
13
13
  ```sh
14
- npm install --save-exact @keenaioc/data-view@0.2.0-alpha.11
14
+ npm install --save-exact @keenaioc/data-view@0.2.0-alpha.14
15
15
  ```
16
16
 
17
17
  必須固定精確版本;不要使用無版本安裝、`latest`、`next` 或範圍版本。
@@ -77,3 +77,5 @@ alpha.10 同時提供附件迴紋針入口與預設單一關聯的直接選單
77
77
  alpha.11 加入依視圖保存的分組順序:拖曳、逐格或頂底移動、還原預設;空白分組也可移動。詳見 INTEGRATION.md。
78
78
 
79
79
  alpha.11 的表頭懸浮選單可直接重新命名、複製、隱藏、固定、排序、篩選、分組與確認刪除。結構修改需要 host 的 `onFieldChange` 與管理權限;可用 `features.columnMenu: false` 關閉入口。
80
+
81
+ alpha.12 關聯選單開啟後有搜尋框,可篩選名稱及名稱中的編號;搜尋範圍為 host 已提供的授權 options,寫入仍使用永久 ID。
@@ -0,0 +1,37 @@
1
+ export type ActionMenuItem<Action extends string> = {
2
+ action: Action;
3
+ label: string;
4
+ icon: string;
5
+ disabled?: boolean;
6
+ reason?: string;
7
+ danger?: boolean;
8
+ separator?: boolean;
9
+ };
10
+ export declare function actionMenuPosition(anchor: {
11
+ left: number;
12
+ right: number;
13
+ top: number;
14
+ bottom: number;
15
+ }, menu: {
16
+ width: number;
17
+ height: number;
18
+ }, viewport: {
19
+ width: number;
20
+ height: number;
21
+ }): {
22
+ left: number;
23
+ top: number;
24
+ };
25
+ export declare function ActionMenu<Action extends string>({ id, label, anchor, point, items, onChoose, onClose }: {
26
+ id: string;
27
+ label: string;
28
+ anchor: HTMLElement;
29
+ point?: {
30
+ x: number;
31
+ y: number;
32
+ };
33
+ items: ActionMenuItem<Action>[];
34
+ onChoose: (action: Action) => void;
35
+ onClose: () => void;
36
+ }): import("react/jsx-runtime").JSX.Element;
37
+ //# sourceMappingURL=action-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-menu.d.ts","sourceRoot":"","sources":["../src/action-menu.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,CAAC,MAAM,SAAS,MAAM,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhL,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;EAE5L;AAED,wBAAgB,UAAU,CAAC,MAAM,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,2CAkCvR"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { DataViewDialog } from "./v2-panels.js";
4
+ export function actionMenuPosition(anchor, menu, viewport) {
5
+ return { left: Math.max(8, Math.min(anchor.right - menu.width, viewport.width - menu.width - 8)), top: Math.max(8, Math.min(anchor.bottom + 4 + menu.height <= viewport.height - 8 ? anchor.bottom + 4 : anchor.top - menu.height - 4, viewport.height - menu.height - 8)) };
6
+ }
7
+ export function ActionMenu({ id, label, anchor, point, items, onChoose, onClose }) {
8
+ const ref = useRef(null);
9
+ const close = useRef(onClose);
10
+ close.current = onClose;
11
+ const [fallback, setFallback] = useState(false);
12
+ useEffect(() => {
13
+ const menu = ref.current;
14
+ if (!menu)
15
+ return;
16
+ if (typeof menu.showPopover !== "function") {
17
+ setFallback(true);
18
+ return;
19
+ }
20
+ const dismiss = (event) => { if (event.newState === "closed")
21
+ close.current(); };
22
+ const moved = (event) => { if (!(event.target instanceof Node) || !menu.contains(event.target))
23
+ close.current(); };
24
+ menu.addEventListener("toggle", dismiss);
25
+ menu.showPopover();
26
+ const position = actionMenuPosition(point ? { left: point.x, right: point.x + menu.getBoundingClientRect().width, top: point.y, bottom: point.y } : anchor.getBoundingClientRect(), menu.getBoundingClientRect(), { width: window.innerWidth, height: window.innerHeight });
27
+ menu.style.left = `${position.left}px`;
28
+ menu.style.top = `${position.top}px`;
29
+ (menu.querySelector("button:not(:disabled)") ?? menu).focus();
30
+ window.addEventListener("scroll", moved, true);
31
+ window.addEventListener("resize", moved);
32
+ return () => { menu.removeEventListener("toggle", dismiss); window.removeEventListener("scroll", moved, true); window.removeEventListener("resize", moved); if (menu.matches(":popover-open"))
33
+ menu.hidePopover(); };
34
+ }, [anchor, point]);
35
+ function keyDown(event) {
36
+ const menu = event.currentTarget;
37
+ if (event.key === "Tab" && !fallback) {
38
+ anchor.focus();
39
+ onClose();
40
+ return;
41
+ }
42
+ if (event.key === "Escape") {
43
+ event.preventDefault();
44
+ event.stopPropagation();
45
+ anchor.focus();
46
+ onClose();
47
+ return;
48
+ }
49
+ const buttons = [...menu.querySelectorAll("button:not(:disabled)")];
50
+ if (!buttons.length || !["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key))
51
+ return;
52
+ event.preventDefault();
53
+ event.stopPropagation();
54
+ const index = buttons.indexOf(document.activeElement);
55
+ const target = event.key === "Home" ? 0 : event.key === "End" ? buttons.length - 1 : (index + (event.key === "ArrowDown" ? 1 : -1) + buttons.length) % buttons.length;
56
+ buttons[target].focus();
57
+ }
58
+ const body = _jsx("div", { id: fallback ? id : undefined, role: fallback ? "menu" : undefined, "aria-label": fallback ? label : undefined, onKeyDown: keyDown, children: items.map((item) => _jsxs("button", { type: "button", role: "menuitem", tabIndex: fallback ? 0 : -1, disabled: item.disabled, title: item.reason, className: `${item.danger ? "hy-dv-danger" : ""} ${item.separator ? "has-separator" : ""}`, onClick: () => { anchor.focus(); onChoose(item.action); }, children: [_jsx("span", { "aria-hidden": "true", children: item.icon }), _jsx("span", { children: item.label })] }, item.action)) });
59
+ if (fallback)
60
+ return _jsx(DataViewDialog, { title: label, onClose: () => { anchor.focus(); onClose(); }, children: _jsx("div", { className: "hy-dv-header-menu-fallback", children: body }) });
61
+ return _jsx("div", { id: id, ref: ref, popover: "auto", role: "menu", tabIndex: -1, "aria-label": label, className: "hy-dv-header-menu", onBlur: (event) => { if (event.relatedTarget instanceof Node && event.relatedTarget !== anchor && !event.currentTarget.contains(event.relatedTarget))
62
+ onClose(); }, children: body });
63
+ }
64
+ //# sourceMappingURL=action-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-menu.js","sourceRoot":"","sources":["../src/action-menu.tsx"],"names":[],"mappings":"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"}
@@ -1,20 +1,6 @@
1
1
  import type { HeaderAction, HeaderItem } from "./column-actions.js";
2
- export declare function columnMenuPosition(anchor: {
3
- left: number;
4
- right: number;
5
- top: number;
6
- bottom: number;
7
- }, menu: {
8
- width: number;
9
- height: number;
10
- }, viewport: {
11
- width: number;
12
- height: number;
13
- }): {
14
- left: number;
15
- top: number;
16
- };
17
- export declare function ColumnMenu({ id, label, anchor, items, onChoose, onClose }: {
2
+ export { actionMenuPosition as columnMenuPosition } from "./action-menu.js";
3
+ export declare function ColumnMenu(props: {
18
4
  id: string;
19
5
  label: string;
20
6
  anchor: HTMLButtonElement;
@@ -1 +1 @@
1
- {"version":3,"file":"column-menu.d.ts","sourceRoot":"","sources":["../src/column-menu.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;;;EAE5L;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,2CAkCvN"}
1
+ {"version":3,"file":"column-menu.d.ts","sourceRoot":"","sources":["../src/column-menu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,kBAAkB,IAAI,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,2CAE7K"}
@@ -1,64 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
3
- import { DataViewDialog } from "./v2-panels.js";
4
- export function columnMenuPosition(anchor, menu, viewport) {
5
- return { left: Math.max(8, Math.min(anchor.right - menu.width, viewport.width - menu.width - 8)), top: Math.max(8, Math.min(anchor.bottom + 4 + menu.height <= viewport.height - 8 ? anchor.bottom + 4 : anchor.top - menu.height - 4, viewport.height - menu.height - 8)) };
6
- }
7
- export function ColumnMenu({ id, label, anchor, items, onChoose, onClose }) {
8
- const ref = useRef(null);
9
- const close = useRef(onClose);
10
- close.current = onClose;
11
- const [fallback, setFallback] = useState(false);
12
- useEffect(() => {
13
- const menu = ref.current;
14
- if (!menu)
15
- return;
16
- if (typeof menu.showPopover !== "function") {
17
- setFallback(true);
18
- return;
19
- }
20
- const dismiss = (event) => { if (event.newState === "closed")
21
- close.current(); };
22
- const moved = (event) => { if (!(event.target instanceof Node) || !menu.contains(event.target))
23
- close.current(); };
24
- menu.addEventListener("toggle", dismiss);
25
- menu.showPopover();
26
- const position = columnMenuPosition(anchor.getBoundingClientRect(), menu.getBoundingClientRect(), { width: window.innerWidth, height: window.innerHeight });
27
- menu.style.left = `${position.left}px`;
28
- menu.style.top = `${position.top}px`;
29
- (menu.querySelector("button:not(:disabled)") ?? menu).focus();
30
- window.addEventListener("scroll", moved, true);
31
- window.addEventListener("resize", moved);
32
- return () => { menu.removeEventListener("toggle", dismiss); window.removeEventListener("scroll", moved, true); window.removeEventListener("resize", moved); if (menu.matches(":popover-open"))
33
- menu.hidePopover(); };
34
- }, [anchor]);
35
- function keyDown(event) {
36
- const menu = event.currentTarget;
37
- if (event.key === "Tab" && !fallback) {
38
- anchor.focus();
39
- onClose();
40
- return;
41
- }
42
- if (event.key === "Escape") {
43
- event.preventDefault();
44
- event.stopPropagation();
45
- anchor.focus();
46
- onClose();
47
- return;
48
- }
49
- const buttons = [...menu.querySelectorAll("button:not(:disabled)")];
50
- if (!buttons.length || !["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key))
51
- return;
52
- event.preventDefault();
53
- event.stopPropagation();
54
- const index = buttons.indexOf(document.activeElement);
55
- const target = event.key === "Home" ? 0 : event.key === "End" ? buttons.length - 1 : (index + (event.key === "ArrowDown" ? 1 : -1) + buttons.length) % buttons.length;
56
- buttons[target].focus();
57
- }
58
- const body = _jsx("div", { id: fallback ? id : undefined, role: fallback ? "menu" : undefined, "aria-label": fallback ? `${label}欄位操作` : undefined, onKeyDown: keyDown, children: items.map((item) => _jsxs("button", { type: "button", role: "menuitem", tabIndex: fallback ? 0 : -1, disabled: item.disabled, title: item.reason, className: `${item.danger ? "hy-dv-danger" : ""} ${item.separator ? "has-separator" : ""}`, onClick: () => { anchor.focus(); onChoose(item.action); }, children: [_jsx("span", { "aria-hidden": "true", children: item.icon }), _jsx("span", { children: item.label })] }, item.action)) });
59
- if (fallback)
60
- return _jsx(DataViewDialog, { title: `${label}欄位操作`, onClose: () => { anchor.focus(); onClose(); }, children: _jsx("div", { className: "hy-dv-header-menu-fallback", children: body }) });
61
- return _jsx("div", { id: id, ref: ref, popover: "auto", role: "menu", tabIndex: -1, "aria-label": `${label}欄位操作`, className: "hy-dv-header-menu", onBlur: (event) => { if (event.relatedTarget instanceof Node && event.relatedTarget !== anchor && !event.currentTarget.contains(event.relatedTarget))
62
- onClose(); }, children: body });
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ActionMenu } from "./action-menu.js";
3
+ export { actionMenuPosition as columnMenuPosition } from "./action-menu.js";
4
+ export function ColumnMenu(props) {
5
+ return _jsx(ActionMenu, { ...props, label: `${props.label}欄位操作` });
63
6
  }
64
7
  //# sourceMappingURL=column-menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"column-menu.js","sourceRoot":"","sources":["../src/column-menu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"column-menu.js","sourceRoot":"","sources":["../src/column-menu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,kBAAkB,IAAI,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,MAAM,UAAU,UAAU,CAAC,KAAmJ;IAC5K,OAAO,KAAC,UAAU,OAAK,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,MAAM,GAAI,CAAC;AAChE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"data-view.d.ts","sourceRoot":"","sources":["../src/data-view.tsx"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAIV,aAAa,EAWd,MAAM,YAAY,CAAC;AAQpB,wBAAgB,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,2CAEtD"}
1
+ {"version":3,"file":"data-view.d.ts","sourceRoot":"","sources":["../src/data-view.tsx"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EAIV,aAAa,EAYd,MAAM,YAAY,CAAC;AASpB,wBAAgB,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,2CAEtD"}