@stonecrop/desktop 0.10.9 → 0.10.11

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.
@@ -80,4 +80,19 @@ export type RecordOpenEventPayload = {
80
80
  doctype: string;
81
81
  recordId: string;
82
82
  };
83
+ /**
84
+ * Payload emitted with the 'load-records' event when Desktop needs records for a list view
85
+ * @public
86
+ */
87
+ export type LoadRecordsEventPayload = {
88
+ doctype: string;
89
+ };
90
+ /**
91
+ * Payload emitted with the 'load-record' event when Desktop needs a single record
92
+ * @public
93
+ */
94
+ export type LoadRecordEventPayload = {
95
+ doctype: string;
96
+ recordId: string;
97
+ };
83
98
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;CACd,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACzC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GACtC,aAAa,GAAG;IACf,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC3C,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,aAAa,EAAE,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,eAAe,CAAA;AAE5D;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,mHAAmH;IACnH,iBAAiB,EAAE,MAAM,MAAM,CAAA;IAC/B,uFAAuF;IACvF,kBAAkB,EAAE,MAAM,MAAM,CAAA;IAChC,oFAAoF;IACpF,cAAc,EAAE,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvD,sFAAsF;IACtF,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACzB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;CACd,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACzC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACnB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GACtC,aAAa,GAAG;IACf,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAEF;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC3C,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,aAAa,EAAE,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,eAAe,CAAA;AAE5D;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IAC1B,mHAAmH;IACnH,iBAAiB,EAAE,MAAM,MAAM,CAAA;IAC/B,uFAAuF;IACvF,kBAAkB,EAAE,MAAM,MAAM,CAAA;IAChC,oFAAoF;IACpF,cAAc,EAAE,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvD,sFAAsF;IACtF,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACzB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CAChB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/desktop",
3
- "version": "0.10.9",
3
+ "version": "0.10.11",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -32,10 +32,10 @@
32
32
  "**/*.css"
33
33
  ],
34
34
  "dependencies": {
35
- "@stonecrop/aform": "0.10.9",
36
- "@stonecrop/stonecrop": "0.10.9",
37
- "@stonecrop/themes": "0.10.9",
38
- "@stonecrop/atable": "0.10.9"
35
+ "@stonecrop/atable": "0.10.11",
36
+ "@stonecrop/themes": "0.10.11",
37
+ "@stonecrop/aform": "0.10.11",
38
+ "@stonecrop/stonecrop": "0.10.11"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "vue": "^3.5.28"
@@ -15,9 +15,7 @@
15
15
  x="0px"
16
16
  y="0px"
17
17
  viewBox="0 0 100 100"
18
- xml:space="preserve"
19
- width="50"
20
- height="50">
18
+ xml:space="preserve">
21
19
  <polygon points="54.2,33.4 29.2,58.8 25,54.6 50,29.2 " />
22
20
  </svg>
23
21
 
@@ -30,9 +28,7 @@
30
28
  x="0px"
31
29
  y="0px"
32
30
  viewBox="0 0 100 100"
33
- xml:space="preserve"
34
- width="50"
35
- height="50">
31
+ xml:space="preserve">
36
32
  <polygon points="70.8,58.8 45.8,33.4 50,29.2 75,54.6 " />
37
33
  </svg>
38
34
  </div>
@@ -127,6 +123,11 @@ const handleClick = (action: (() => void | Promise<void>) | undefined, label: st
127
123
  transform: rotate(90deg);
128
124
  }
129
125
 
126
+ #chevron svg {
127
+ width: 1.5em;
128
+ height: 1.5em;
129
+ }
130
+
130
131
  .leftBar,
131
132
  .rightBar {
132
133
  transition-duration: 0.225s;
@@ -44,6 +44,8 @@ import type {
44
44
  NavigationTarget,
45
45
  ActionEventPayload,
46
46
  RecordOpenEventPayload,
47
+ LoadRecordsEventPayload,
48
+ LoadRecordEventPayload,
47
49
  } from '../types'
48
50
 
49
51
  const props = defineProps<{
@@ -60,6 +62,12 @@ const props = defineProps<{
60
62
  * Defaults to the native `window.confirm` if omitted.
61
63
  */
62
64
  confirmFn?: (message: string) => boolean | Promise<boolean>
65
+ /**
66
+ * The field name that holds the canonical record ID (e.g., 'rowId' for UUID).
67
+ * Used for navigation and table row identification.
68
+ * Defaults to 'id' if not specified.
69
+ */
70
+ recordIdField?: string
63
71
  }>()
64
72
 
65
73
  const emit = defineEmits<{
@@ -77,6 +85,16 @@ const emit = defineEmits<{
77
85
  * Fired when the user opens a specific record.
78
86
  */
79
87
  'record:open': [payload: RecordOpenEventPayload]
88
+ /**
89
+ * Fired when Desktop needs records for a list view.
90
+ * The host app should fetch and populate HST.
91
+ */
92
+ 'load-records': [payload: LoadRecordsEventPayload]
93
+ /**
94
+ * Fired when Desktop needs a single record for a form view.
95
+ * The host app should fetch and populate HST.
96
+ */
97
+ 'load-record': [payload: LoadRecordEventPayload]
80
98
  }>()
81
99
 
82
100
  const { availableDoctypes = [] } = props
@@ -493,16 +511,23 @@ const getRecordsSchema = (): SchemaTypes[] => {
493
511
 
494
512
  const records = getRecords()
495
513
  const columns = getColumns()
514
+ const idField = props.recordIdField || 'id'
496
515
 
497
516
  // If no columns are available, let the template fallback handle the loading state
498
517
  if (columns.length === 0) {
499
518
  return []
500
519
  }
501
520
 
521
+ // Ensure the ID column is first so click handler can reliably find it
522
+ const idColumn = columns.find(c => c.fieldname === idField)
523
+ const otherColumns = columns.filter(c => c.fieldname !== idField)
524
+ const orderedColumns = idColumn ? [idColumn, ...otherColumns] : columns
525
+
502
526
  const rows = records.map((record: any) => ({
503
527
  ...record,
528
+ // Use the canonical ID field for navigation
504
529
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
505
- id: record.id || '',
530
+ id: record[idField] || record.id || '',
506
531
  actions: 'Edit | Delete',
507
532
  }))
508
533
 
@@ -511,7 +536,7 @@ const getRecordsSchema = (): SchemaTypes[] => {
511
536
  fieldname: 'records_table',
512
537
  component: 'ATable',
513
538
  columns: [
514
- ...columns.map(col => ({
539
+ ...orderedColumns.map(col => ({
515
540
  label: col.label,
516
541
  name: col.fieldname,
517
542
  fieldtype: col.fieldtype,
@@ -637,6 +662,25 @@ const handleDelete = async (recordId?: string) => {
637
662
  }
638
663
 
639
664
  // Event handlers
665
+ const getRecordIdFromRow = (rowElement: HTMLTableRowElement): string | null => {
666
+ const cell = rowElement.querySelector('td[data-rowindex]')
667
+ if (!cell) return null
668
+
669
+ const rowIndexAttr = cell.getAttribute('data-rowindex')
670
+ if (rowIndexAttr === null) return null
671
+
672
+ const rowIndex = parseInt(rowIndexAttr, 10)
673
+ if (isNaN(rowIndex)) return null
674
+
675
+ const records = getRecords()
676
+ const record = records[rowIndex]
677
+ if (!record) return null
678
+
679
+ const idField = props.recordIdField || 'id'
680
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
681
+ return record[idField] || record.id || null
682
+ }
683
+
640
684
  const handleClick = async (event: Event) => {
641
685
  const target = event.target as HTMLElement
642
686
  const action = target.getAttribute('data-action')
@@ -645,7 +689,6 @@ const handleClick = async (event: Event) => {
645
689
  await createNewRecord()
646
690
  }
647
691
 
648
- // Handle table cell clicks for actions
649
692
  const cell = target.closest('td, th')
650
693
  if (cell) {
651
694
  const cellText = cell.textContent?.trim()
@@ -662,24 +705,14 @@ const handleClick = async (event: Event) => {
662
705
  }
663
706
  }
664
707
  } else if (cellText?.includes('Edit') && row) {
665
- // Get the record ID from the row
666
- const cells = row.querySelectorAll('td')
667
- if (cells.length > 0) {
668
- const idCell = cells[0] // Assuming ID is in first column
669
- const recordId = idCell.textContent?.trim()
670
- if (recordId) {
671
- await openRecord(recordId)
672
- }
708
+ const recordId = getRecordIdFromRow(row)
709
+ if (recordId) {
710
+ await openRecord(recordId)
673
711
  }
674
712
  } else if (cellText?.includes('Delete') && row) {
675
- // Get the record ID from the row
676
- const cells = row.querySelectorAll('td')
677
- if (cells.length > 0) {
678
- const idCell = cells[0] // Assuming ID is in first column
679
- const recordId = idCell.textContent?.trim()
680
- if (recordId) {
681
- await handleDelete(recordId)
682
- }
713
+ const recordId = getRecordIdFromRow(row)
714
+ if (recordId) {
715
+ await handleDelete(recordId)
683
716
  }
684
717
  }
685
718
  }
@@ -709,7 +742,12 @@ const loadRecordData = () => {
709
742
  watch(
710
743
  [currentView, currentDoctype, currentRecordId],
711
744
  () => {
712
- if (currentView.value === 'record') {
745
+ if (currentView.value === 'records' && currentDoctype.value) {
746
+ // Emit load-records event so host app can populate HST
747
+ emit('load-records', { doctype: currentDoctype.value })
748
+ } else if (currentView.value === 'record' && currentDoctype.value && currentRecordId.value) {
749
+ // Emit load-record event so host app can fetch and populate HST
750
+ emit('load-record', { doctype: currentDoctype.value, recordId: currentRecordId.value })
713
751
  loadRecordData()
714
752
  }
715
753
  },
@@ -89,3 +89,20 @@ export type RecordOpenEventPayload = {
89
89
  doctype: string
90
90
  recordId: string
91
91
  }
92
+
93
+ /**
94
+ * Payload emitted with the 'load-records' event when Desktop needs records for a list view
95
+ * @public
96
+ */
97
+ export type LoadRecordsEventPayload = {
98
+ doctype: string
99
+ }
100
+
101
+ /**
102
+ * Payload emitted with the 'load-record' event when Desktop needs a single record
103
+ * @public
104
+ */
105
+ export type LoadRecordEventPayload = {
106
+ doctype: string
107
+ recordId: string
108
+ }