@pancake-pos/ui-extensions 2026.1.6 → 2026.1.7

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.
@@ -47,6 +47,8 @@ export interface PosButtonProps {
47
47
  size?: "small" | "medium";
48
48
  loading?: boolean;
49
49
  disabled?: boolean;
50
+ icon?: "plus" | "edit" | "delete" | "download" | "upload" | "refresh" | "filter" | "search" | "settings" | "print" | "copy" | "link" | "external" | "view" | "send" | "check" | "close" | "more" | "calendar" | "info" | "warning";
51
+ tooltip?: string;
50
52
  }
51
53
  /** Sự kiện của `<pos-button>` → kiểu `event.detail`. */
52
54
  export interface PosButtonEvents {
@@ -67,17 +69,25 @@ export interface PosChartProps {
67
69
  series?: ({
68
70
  key: string;
69
71
  label: string;
70
- format?: "number" | "money";
72
+ format?: "number" | "money" | "percent";
73
+ type?: "line" | "bar";
71
74
  })[];
72
75
  stacked?: boolean;
76
+ horizontal?: boolean;
73
77
  height?: number;
74
78
  loading?: boolean;
75
79
  emptyText?: string;
80
+ selected?: string | number | null;
76
81
  }
77
82
  /** Sự kiện của `<pos-chart>` → kiểu `event.detail`. */
78
83
  export interface PosChartEvents {
84
+ select: {
85
+ x: string | number | null;
86
+ series: string | null;
87
+ };
79
88
  }
80
89
  export interface PosChartAttributes extends PosChartProps, PosBaseAttributes {
90
+ onSelect?: (event: PosEvent<PosChartEvents["select"]>) => void;
81
91
  }
82
92
  export interface PosChartElement extends PosChartProps {
83
93
  scrollIntoView(): void;
@@ -128,6 +138,55 @@ export interface PosDatePickerElement extends PosDatePickerProps {
128
138
  focus(): void;
129
139
  scrollIntoView(): void;
130
140
  }
141
+ /** Thuộc tính của `<pos-date-range>`. */
142
+ export interface PosDateRangeProps {
143
+ label?: string;
144
+ disabled?: boolean;
145
+ required?: boolean;
146
+ error?: string;
147
+ help?: string;
148
+ value?: {
149
+ from: string;
150
+ to: string;
151
+ } | null;
152
+ min?: string;
153
+ max?: string;
154
+ presets?: boolean;
155
+ }
156
+ /** Sự kiện của `<pos-date-range>` → kiểu `event.detail`. */
157
+ export interface PosDateRangeEvents {
158
+ change: {
159
+ from: string;
160
+ to: string;
161
+ } | null;
162
+ blur: null;
163
+ }
164
+ export interface PosDateRangeAttributes extends PosDateRangeProps, PosBaseAttributes {
165
+ onChange?: (event: PosEvent<PosDateRangeEvents["change"]>) => void;
166
+ onBlur?: (event: PosEvent<PosDateRangeEvents["blur"]>) => void;
167
+ }
168
+ export interface PosDateRangeElement extends PosDateRangeProps {
169
+ focus(): void;
170
+ scrollIntoView(): void;
171
+ }
172
+ /** Thuộc tính của `<pos-description-list>`. */
173
+ export interface PosDescriptionListProps {
174
+ items?: ({
175
+ label: string;
176
+ value?: string | number | null;
177
+ format?: "text" | "number" | "money" | "percent" | "date" | "datetime" | "badge";
178
+ tone?: "default" | "info" | "success" | "warning" | "critical";
179
+ })[];
180
+ columns?: number;
181
+ }
182
+ /** Sự kiện của `<pos-description-list>` → kiểu `event.detail`. */
183
+ export interface PosDescriptionListEvents {
184
+ }
185
+ export interface PosDescriptionListAttributes extends PosDescriptionListProps, PosBaseAttributes {
186
+ }
187
+ export interface PosDescriptionListElement extends PosDescriptionListProps {
188
+ scrollIntoView(): void;
189
+ }
131
190
  /** Thuộc tính của `<pos-divider>`. */
132
191
  export interface PosDividerProps {
133
192
  }
@@ -139,6 +198,35 @@ export interface PosDividerAttributes extends PosDividerProps, PosBaseAttributes
139
198
  export interface PosDividerElement extends PosDividerProps {
140
199
  scrollIntoView(): void;
141
200
  }
201
+ /** Thuộc tính của `<pos-drawer>`. */
202
+ export interface PosDrawerProps {
203
+ open?: boolean;
204
+ heading?: string;
205
+ width?: "small" | "medium" | "large";
206
+ }
207
+ /** Sự kiện của `<pos-drawer>` → kiểu `event.detail`. */
208
+ export interface PosDrawerEvents {
209
+ close: null;
210
+ }
211
+ export interface PosDrawerAttributes extends PosDrawerProps, PosBaseAttributes {
212
+ onClose?: (event: PosEvent<PosDrawerEvents["close"]>) => void;
213
+ }
214
+ export interface PosDrawerElement extends PosDrawerProps {
215
+ scrollIntoView(): void;
216
+ }
217
+ /** Thuộc tính của `<pos-empty>`. */
218
+ export interface PosEmptyProps {
219
+ heading?: string;
220
+ description?: string;
221
+ }
222
+ /** Sự kiện của `<pos-empty>` → kiểu `event.detail`. */
223
+ export interface PosEmptyEvents {
224
+ }
225
+ export interface PosEmptyAttributes extends PosEmptyProps, PosBaseAttributes {
226
+ }
227
+ export interface PosEmptyElement extends PosEmptyProps {
228
+ scrollIntoView(): void;
229
+ }
142
230
  /** Thuộc tính của `<pos-filter-bar>`. */
143
231
  export interface PosFilterBarProps {
144
232
  }
@@ -206,6 +294,32 @@ export interface PosLinkElement extends PosLinkProps {
206
294
  focus(): void;
207
295
  scrollIntoView(): void;
208
296
  }
297
+ /** Thuộc tính của `<pos-menu-button>`. */
298
+ export interface PosMenuButtonProps {
299
+ label?: string;
300
+ icon?: "plus" | "edit" | "delete" | "download" | "upload" | "refresh" | "filter" | "search" | "settings" | "print" | "copy" | "link" | "external" | "view" | "send" | "check" | "close" | "more" | "calendar" | "info" | "warning";
301
+ variant?: "primary" | "secondary" | "tertiary";
302
+ size?: "small" | "medium";
303
+ disabled?: boolean;
304
+ tooltip?: string;
305
+ items?: {
306
+ id: string;
307
+ label: string;
308
+ danger?: boolean;
309
+ disabled?: boolean;
310
+ }[];
311
+ }
312
+ /** Sự kiện của `<pos-menu-button>` → kiểu `event.detail`. */
313
+ export interface PosMenuButtonEvents {
314
+ select: string;
315
+ }
316
+ export interface PosMenuButtonAttributes extends PosMenuButtonProps, PosBaseAttributes {
317
+ onSelect?: (event: PosEvent<PosMenuButtonEvents["select"]>) => void;
318
+ }
319
+ export interface PosMenuButtonElement extends PosMenuButtonProps {
320
+ focus(): void;
321
+ scrollIntoView(): void;
322
+ }
209
323
  /** Thuộc tính của `<pos-modal>`. */
210
324
  export interface PosModalProps {
211
325
  open?: boolean;
@@ -275,6 +389,21 @@ export interface PosPageAttributes extends PosPageProps, PosBaseAttributes {
275
389
  export interface PosPageElement extends PosPageProps {
276
390
  scrollIntoView(): void;
277
391
  }
392
+ /** Thuộc tính của `<pos-progress>`. */
393
+ export interface PosProgressProps {
394
+ value?: number;
395
+ label?: string;
396
+ tone?: "default" | "info" | "success" | "warning" | "critical";
397
+ showValue?: boolean;
398
+ }
399
+ /** Sự kiện của `<pos-progress>` → kiểu `event.detail`. */
400
+ export interface PosProgressEvents {
401
+ }
402
+ export interface PosProgressAttributes extends PosProgressProps, PosBaseAttributes {
403
+ }
404
+ export interface PosProgressElement extends PosProgressProps {
405
+ scrollIntoView(): void;
406
+ }
278
407
  /** Thuộc tính của `<pos-section>`. */
279
408
  export interface PosSectionProps {
280
409
  heading?: string;
@@ -346,6 +475,30 @@ export interface PosStackAttributes extends PosStackProps, PosBaseAttributes {
346
475
  export interface PosStackElement extends PosStackProps {
347
476
  scrollIntoView(): void;
348
477
  }
478
+ /** Thuộc tính của `<pos-stat>`. */
479
+ export interface PosStatProps {
480
+ label?: string;
481
+ value?: number | string | null;
482
+ format?: "number" | "money" | "percent";
483
+ currency?: string;
484
+ tone?: "default" | "info" | "success" | "warning" | "critical";
485
+ help?: string;
486
+ change?: number;
487
+ changeLabel?: string;
488
+ inverse?: boolean;
489
+ selected?: boolean;
490
+ loading?: boolean;
491
+ }
492
+ /** Sự kiện của `<pos-stat>` → kiểu `event.detail`. */
493
+ export interface PosStatEvents {
494
+ click: null;
495
+ }
496
+ export interface PosStatAttributes extends PosStatProps, PosBaseAttributes {
497
+ onClick?: (event: PosEvent<PosStatEvents["click"]>) => void;
498
+ }
499
+ export interface PosStatElement extends PosStatProps {
500
+ scrollIntoView(): void;
501
+ }
349
502
  /** Thuộc tính của `<pos-table>`. */
350
503
  export interface PosTableProps {
351
504
  columns?: ({
@@ -353,7 +506,12 @@ export interface PosTableProps {
353
506
  title: string;
354
507
  align?: "left" | "center" | "right";
355
508
  width?: number;
356
- format?: "text" | "number" | "money" | "date" | "datetime";
509
+ format?: "text" | "number" | "money" | "percent" | "date" | "datetime" | "badge" | "link";
510
+ tones?: Record<string, "default" | "info" | "success" | "warning" | "critical">;
511
+ subtitle?: string;
512
+ sortable?: boolean;
513
+ fixed?: "left" | "right";
514
+ ellipsis?: boolean;
357
515
  })[];
358
516
  rows?: (Record<string, string | number | boolean | null>)[];
359
517
  rowKey?: string;
@@ -364,6 +522,13 @@ export interface PosTableProps {
364
522
  total: number;
365
523
  } | null;
366
524
  emptyText?: string;
525
+ sort?: {
526
+ key: string;
527
+ order: "asc" | "desc";
528
+ } | null;
529
+ summary?: Record<string, string | number | boolean | null> | null;
530
+ selectable?: boolean;
531
+ selected?: (string | number)[];
367
532
  }
368
533
  /** Sự kiện của `<pos-table>` → kiểu `event.detail`. */
369
534
  export interface PosTableEvents {
@@ -372,10 +537,22 @@ export interface PosTableEvents {
372
537
  pageSize: number;
373
538
  };
374
539
  rowclick: Record<string, string | number | boolean | null>;
540
+ sortchange: {
541
+ key: string;
542
+ order: "asc" | "desc";
543
+ } | null;
544
+ selectionchange: (string | number)[];
545
+ cellclick: {
546
+ key: string;
547
+ row: Record<string, string | number | boolean | null>;
548
+ };
375
549
  }
376
550
  export interface PosTableAttributes extends PosTableProps, PosBaseAttributes {
377
551
  onPageChange?: (event: PosEvent<PosTableEvents["pagechange"]>) => void;
378
552
  onRowClick?: (event: PosEvent<PosTableEvents["rowclick"]>) => void;
553
+ onSortChange?: (event: PosEvent<PosTableEvents["sortchange"]>) => void;
554
+ onSelectionChange?: (event: PosEvent<PosTableEvents["selectionchange"]>) => void;
555
+ onCellClick?: (event: PosEvent<PosTableEvents["cellclick"]>) => void;
379
556
  }
380
557
  export interface PosTableElement extends PosTableProps {
381
558
  scrollIntoView(): void;
@@ -439,6 +616,23 @@ export interface PosTextFieldElement extends PosTextFieldProps {
439
616
  focus(): void;
440
617
  scrollIntoView(): void;
441
618
  }
619
+ /** Thuộc tính của `<pos-timeline>`. */
620
+ export interface PosTimelineProps {
621
+ items?: ({
622
+ title: string;
623
+ time?: string;
624
+ description?: string;
625
+ tone?: "default" | "info" | "success" | "warning" | "critical";
626
+ })[];
627
+ }
628
+ /** Sự kiện của `<pos-timeline>` → kiểu `event.detail`. */
629
+ export interface PosTimelineEvents {
630
+ }
631
+ export interface PosTimelineAttributes extends PosTimelineProps, PosBaseAttributes {
632
+ }
633
+ export interface PosTimelineElement extends PosTimelineProps {
634
+ scrollIntoView(): void;
635
+ }
442
636
  /** Tên element → thuộc tính trong JSX. */
443
637
  export interface PosIntrinsicElements {
444
638
  "pos-badge": PosBadgeAttributes;
@@ -447,24 +641,32 @@ export interface PosIntrinsicElements {
447
641
  "pos-chart": PosChartAttributes;
448
642
  "pos-checkbox": PosCheckboxAttributes;
449
643
  "pos-date-picker": PosDatePickerAttributes;
644
+ "pos-date-range": PosDateRangeAttributes;
645
+ "pos-description-list": PosDescriptionListAttributes;
450
646
  "pos-divider": PosDividerAttributes;
647
+ "pos-drawer": PosDrawerAttributes;
648
+ "pos-empty": PosEmptyAttributes;
451
649
  "pos-filter-bar": PosFilterBarAttributes;
452
650
  "pos-grid": PosGridAttributes;
453
651
  "pos-heading": PosHeadingAttributes;
454
652
  "pos-image": PosImageAttributes;
455
653
  "pos-link": PosLinkAttributes;
654
+ "pos-menu-button": PosMenuButtonAttributes;
456
655
  "pos-modal": PosModalAttributes;
457
656
  "pos-money": PosMoneyAttributes;
458
657
  "pos-number-field": PosNumberFieldAttributes;
459
658
  "pos-page": PosPageAttributes;
659
+ "pos-progress": PosProgressAttributes;
460
660
  "pos-section": PosSectionAttributes;
461
661
  "pos-select": PosSelectAttributes;
462
662
  "pos-spinner": PosSpinnerAttributes;
463
663
  "pos-stack": PosStackAttributes;
664
+ "pos-stat": PosStatAttributes;
464
665
  "pos-table": PosTableAttributes;
465
666
  "pos-tabs": PosTabsAttributes;
466
667
  "pos-text": PosTextAttributes;
467
668
  "pos-text-field": PosTextFieldAttributes;
669
+ "pos-timeline": PosTimelineAttributes;
468
670
  }
469
671
  /** Tên element → element tạo bằng `document.createElement` (JS thuần). */
470
672
  export interface PosHTMLElementTagNameMap {
@@ -474,22 +676,30 @@ export interface PosHTMLElementTagNameMap {
474
676
  "pos-chart": Omit<HTMLElement, keyof PosChartElement> & PosChartElement;
475
677
  "pos-checkbox": Omit<HTMLElement, keyof PosCheckboxElement> & PosCheckboxElement;
476
678
  "pos-date-picker": Omit<HTMLElement, keyof PosDatePickerElement> & PosDatePickerElement;
679
+ "pos-date-range": Omit<HTMLElement, keyof PosDateRangeElement> & PosDateRangeElement;
680
+ "pos-description-list": Omit<HTMLElement, keyof PosDescriptionListElement> & PosDescriptionListElement;
477
681
  "pos-divider": Omit<HTMLElement, keyof PosDividerElement> & PosDividerElement;
682
+ "pos-drawer": Omit<HTMLElement, keyof PosDrawerElement> & PosDrawerElement;
683
+ "pos-empty": Omit<HTMLElement, keyof PosEmptyElement> & PosEmptyElement;
478
684
  "pos-filter-bar": Omit<HTMLElement, keyof PosFilterBarElement> & PosFilterBarElement;
479
685
  "pos-grid": Omit<HTMLElement, keyof PosGridElement> & PosGridElement;
480
686
  "pos-heading": Omit<HTMLElement, keyof PosHeadingElement> & PosHeadingElement;
481
687
  "pos-image": Omit<HTMLElement, keyof PosImageElement> & PosImageElement;
482
688
  "pos-link": Omit<HTMLElement, keyof PosLinkElement> & PosLinkElement;
689
+ "pos-menu-button": Omit<HTMLElement, keyof PosMenuButtonElement> & PosMenuButtonElement;
483
690
  "pos-modal": Omit<HTMLElement, keyof PosModalElement> & PosModalElement;
484
691
  "pos-money": Omit<HTMLElement, keyof PosMoneyElement> & PosMoneyElement;
485
692
  "pos-number-field": Omit<HTMLElement, keyof PosNumberFieldElement> & PosNumberFieldElement;
486
693
  "pos-page": Omit<HTMLElement, keyof PosPageElement> & PosPageElement;
694
+ "pos-progress": Omit<HTMLElement, keyof PosProgressElement> & PosProgressElement;
487
695
  "pos-section": Omit<HTMLElement, keyof PosSectionElement> & PosSectionElement;
488
696
  "pos-select": Omit<HTMLElement, keyof PosSelectElement> & PosSelectElement;
489
697
  "pos-spinner": Omit<HTMLElement, keyof PosSpinnerElement> & PosSpinnerElement;
490
698
  "pos-stack": Omit<HTMLElement, keyof PosStackElement> & PosStackElement;
699
+ "pos-stat": Omit<HTMLElement, keyof PosStatElement> & PosStatElement;
491
700
  "pos-table": Omit<HTMLElement, keyof PosTableElement> & PosTableElement;
492
701
  "pos-tabs": Omit<HTMLElement, keyof PosTabsElement> & PosTabsElement;
493
702
  "pos-text": Omit<HTMLElement, keyof PosTextElement> & PosTextElement;
494
703
  "pos-text-field": Omit<HTMLElement, keyof PosTextFieldElement> & PosTextFieldElement;
704
+ "pos-timeline": Omit<HTMLElement, keyof PosTimelineElement> & PosTimelineElement;
495
705
  }
package/dist/page.js CHANGED
@@ -1,5 +1,13 @@
1
1
  // ../app-protocol/src/protocol.ts
2
2
  var PROTOCOL_VERSION = 1;
3
+ var DOWNLOAD_TYPES = {
4
+ csv: "text/csv",
5
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
6
+ json: "application/json",
7
+ txt: "text/plain",
8
+ pdf: "application/pdf"
9
+ };
10
+ var MAX_DOWNLOAD_BYTES = 10 * 1024 * 1024;
3
11
  function hostEvents(context) {
4
12
  return context === "page" ? ["primary-action"] : [];
5
13
  }
@@ -21,6 +29,7 @@ var AVAILABILITY = {
21
29
  "element.scrollIntoView": ["block", "action-ui", "page"],
22
30
  "page.setTitle": ["page"],
23
31
  "page.setPrimaryAction": ["page"],
32
+ download: ["block", "action-headless", "action-ui", "page"],
24
33
  "data-change": ["block", "action-ui", "page"]
25
34
  };
26
35
  function isAvailable(capability, context) {
@@ -175,6 +184,35 @@ function createPos(deps) {
175
184
  return await callHost("ui.confirm", [options], "pos.ui.confirm") === true;
176
185
  }
177
186
  }),
187
+ // File do app tạo (CSV, Excel, PDF…): worker không tạo được link tải, POS tải hộ. Nhị phân gửi dạng base64.
188
+ async download(file) {
189
+ require2("download", "pos.download");
190
+ const filename = String(file?.filename ?? "").trim().slice(0, 200);
191
+ const extension = /\.([a-z0-9]+)$/i.exec(filename)?.[1]?.toLowerCase() ?? "";
192
+ const type = file?.type ?? DOWNLOAD_TYPES[extension];
193
+ if (!filename || !type || !Object.values(DOWNLOAD_TYPES).includes(type)) {
194
+ throw new PosRuntimeError("invalid_download", `filename must end with .${Object.keys(DOWNLOAD_TYPES).join(", .")} (or pass a supported type)`);
195
+ }
196
+ let content;
197
+ let encoding;
198
+ let bytes;
199
+ if (typeof file.content === "string") {
200
+ content = file.content;
201
+ encoding = "text";
202
+ bytes = new TextEncoder().encode(content).length;
203
+ } else if (file.content instanceof ArrayBuffer || ArrayBuffer.isView(file.content)) {
204
+ const view = file.content instanceof ArrayBuffer ? new Uint8Array(file.content) : new Uint8Array(file.content.buffer, file.content.byteOffset, file.content.byteLength);
205
+ bytes = view.length;
206
+ let binary = "";
207
+ for (let i = 0; i < view.length; i += 32768) binary += String.fromCharCode(...view.subarray(i, i + 32768));
208
+ content = btoa(binary);
209
+ encoding = "base64";
210
+ } else {
211
+ throw new PosRuntimeError("invalid_download", "content must be a string, ArrayBuffer or typed array");
212
+ }
213
+ if (bytes > MAX_DOWNLOAD_BYTES) throw new PosRuntimeError("invalid_download", `file is larger than ${MAX_DOWNLOAD_BYTES} bytes`);
214
+ await callHost("download", [{ filename, type, content, encoding }], "pos.download");
215
+ },
178
216
  navigate(to) {
179
217
  void callHost("navigate", [to], "pos.navigate");
180
218
  },
package/dist/types.d.ts CHANGED
@@ -231,6 +231,12 @@ export type ConfirmOptions = {
231
231
  cancelText?: string;
232
232
  danger?: boolean;
233
233
  };
234
+ /** `pos.download`: đuôi file quyết định loại (.csv, .xlsx, .json, .txt, .pdf); tối đa 10 MB. */
235
+ export type DownloadFile = {
236
+ filename: string;
237
+ content: string | ArrayBuffer | ArrayBufferView;
238
+ type?: string;
239
+ };
234
240
  export type NavigateTarget = {
235
241
  page: string;
236
242
  path?: string;
@@ -301,6 +307,8 @@ export interface Pos<D = any> {
301
307
  readonly ui: {
302
308
  confirm(options: ConfirmOptions): Promise<boolean>;
303
309
  };
310
+ /** Tải file do app tạo (CSV, Excel, PDF…) về máy người dùng. Không có trong hook. */
311
+ download(file: DownloadFile): Promise<void>;
304
312
  navigate(to: NavigateTarget): void;
305
313
  refresh(): void;
306
314
  close(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pancake-pos/ui-extensions",
3
- "version": "2026.1.6",
3
+ "version": "2026.1.7",
4
4
  "description": "Types for pos and pos-* elements, defineExtension, and connect() for iframe pages of Pancake POS apps",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",