@meddleware/dao-ui 0.1.18 → 0.1.20

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.
@@ -2,13 +2,21 @@
2
2
  // Overview tab: treasury balance + commission, platform activity counters (active gates,
3
3
  // accesses minted/consumed derived from the event feed), and a recent-activity list.
4
4
  import { computed } from 'vue'
5
- import Panel from '../components/Panel.vue'
6
5
  import AmountCell from '../components/AmountCell.vue'
7
6
  import { usePlatformConfig } from '../composables/usePlatformConfig.js'
8
7
  import { useTreasury } from '../composables/useTreasury.js'
9
8
  import { useDaoEvents } from '../composables/useDaoEvents.js'
10
9
  import { useGates } from '../composables/useGates.js'
11
- import { CopyableAddress, ExplorerLink, suiExplorerUrl } from '@meddleware/ui'
10
+ import {
11
+ CopyableAddress,
12
+ ExplorerLink,
13
+ suiExplorerUrl,
14
+ UiPanel,
15
+ UiStatGrid,
16
+ UiStatRow,
17
+ UiActivityFeed,
18
+ UiActivityItem,
19
+ } from '@meddleware/ui'
12
20
  import { NETWORK } from '../config.js'
13
21
  import type { DaoEvent } from '../composables/useDaoEvents.js'
14
22
 
@@ -34,50 +42,41 @@ const accessesConsumed = computed(() => events.value.filter((e) => e.type === 'A
34
42
  <template>
35
43
  <div class="dao-overview-cols">
36
44
  <!-- Left: treasury summary -->
37
- <div style="display: flex; flex-direction: column; gap: 8px">
38
- <Panel title="Treasury Balance">
39
- <div class="dao-stat-grid">
40
- <span class="dao-stat-grid__label">SUI balance</span>
41
- <AmountCell class="dao-stat-grid__value" :mist="balance" />
42
-
43
- <span class="dao-stat-grid__label">Commission rate</span>
44
- <span class="dao-stat-grid__value dao-mono">{{ commissionPct }}</span>
45
-
46
- <span class="dao-stat-grid__label">Treasury address</span>
47
- <span class="dao-stat-grid__value" style="text-align: left">
45
+ <div class="dao-stack dao-stack--tight">
46
+ <UiPanel title="Treasury Balance">
47
+ <UiStatGrid>
48
+ <UiStatRow label="SUI balance"><AmountCell :mist="balance" /></UiStatRow>
49
+ <UiStatRow label="Commission rate">{{ commissionPct }}</UiStatRow>
50
+ <UiStatRow label="Treasury address" align="left">
48
51
  <CopyableAddress v-if="config?.treasury" :address="config.treasury">
49
52
  <ExplorerLink :href="suiExplorerUrl('account', config.treasury, NETWORK)" :value="config.treasury" />
50
53
  </CopyableAddress>
51
- <span v-else class="dao-mono" style="font-size: 0.7rem">—</span>
52
- </span>
53
- </div>
54
- </Panel>
55
-
56
- <Panel title="Platform Activity">
57
- <div class="dao-stat-grid">
58
- <span class="dao-stat-grid__label">Active gates</span>
59
- <span class="dao-stat-grid__value dao-mono">{{ gatesLoading ? '…' : gates.length }}</span>
60
-
61
- <span class="dao-stat-grid__label">Accesses minted</span>
62
- <span class="dao-stat-grid__value dao-mono">{{ accessesMinted || '—' }}</span>
54
+ <span v-else class="dao-mono dao-mono--sm">—</span>
55
+ </UiStatRow>
56
+ </UiStatGrid>
57
+ </UiPanel>
63
58
 
64
- <span class="dao-stat-grid__label">Accesses consumed</span>
65
- <span class="dao-stat-grid__value dao-mono">{{ accessesConsumed || '—' }}</span>
66
- </div>
67
- </Panel>
59
+ <UiPanel title="Platform Activity">
60
+ <UiStatGrid>
61
+ <UiStatRow label="Active gates">{{ gatesLoading ? '…' : gates.length }}</UiStatRow>
62
+ <UiStatRow label="Accesses minted">{{ accessesMinted || '—' }}</UiStatRow>
63
+ <UiStatRow label="Accesses consumed">{{ accessesConsumed || '—' }}</UiStatRow>
64
+ </UiStatGrid>
65
+ </UiPanel>
68
66
  </div>
69
67
 
70
68
  <!-- Right: recent activity -->
71
- <Panel title="Recent Activity">
72
- <p v-if="eventsLoading" class="dao-muted" style="margin: 0">Loading events…</p>
73
- <ul v-else-if="events.length" class="dao-feed">
74
- <li v-for="ev in events" :key="ev.txDigest" class="dao-feed__item">
75
- <span class="dao-feed__dot" />
76
- <span class="dao-feed__type">{{ eventLabel[ev.type] }}</span>
77
- <span class="dao-feed__time">ckpt {{ ev.checkpoint ?? '?' }}</span>
78
- </li>
79
- </ul>
69
+ <UiPanel title="Recent Activity">
70
+ <p v-if="eventsLoading" class="dao-muted dao-flush">Loading events…</p>
71
+ <UiActivityFeed v-else-if="events.length">
72
+ <UiActivityItem
73
+ v-for="ev in events"
74
+ :key="ev.txDigest"
75
+ :type="eventLabel[ev.type]"
76
+ :time="`ckpt ${ev.checkpoint ?? '?'}`"
77
+ />
78
+ </UiActivityFeed>
80
79
  <p v-else class="dao-placeholder">No recent events.</p>
81
- </Panel>
80
+ </UiPanel>
82
81
  </div>
83
82
  </template>
@@ -10,18 +10,13 @@ const { epoch } = useEpoch()
10
10
  </script>
11
11
 
12
12
  <template>
13
- <div>
14
- <template v-if="proposals.length > 0">
15
- <p class="dao-section-title">Active &amp; Pending Proposals</p>
16
- <ProposalRow
17
- v-for="p in proposals"
18
- :key="p.id"
19
- :proposal="p"
20
- :current-epoch="epoch"
21
- />
22
- </template>
23
- <div v-else class="dao-placeholder">
24
- No proposals yet.
25
- </div>
26
- </div>
13
+ <template v-if="proposals.length > 0">
14
+ <h2 class="dao-section-title">Active &amp; Pending Proposals</h2>
15
+ <ul role="list">
16
+ <li v-for="p in proposals" :key="p.id">
17
+ <ProposalRow :proposal="p" :current-epoch="epoch" />
18
+ </li>
19
+ </ul>
20
+ </template>
21
+ <p v-else class="dao-placeholder">No proposals yet.</p>
27
22
  </template>
@@ -2,13 +2,19 @@
2
2
  // Treasury tab: commission rate + live SUI balance + treasury address, plus the table
3
3
  // of Community Gates the treasury controls (discovered via AdminCap ownership).
4
4
  import { computed } from 'vue'
5
- import Panel from '../components/Panel.vue'
6
5
  import AmountCell from '../components/AmountCell.vue'
7
- import DataTable from '../components/DataTable.vue'
8
6
  import { usePlatformConfig } from '../composables/usePlatformConfig.js'
9
7
  import { useTreasury } from '../composables/useTreasury.js'
10
8
  import { useGates } from '../composables/useGates.js'
11
- import { CopyableAddress, ExplorerLink, suiExplorerUrl } from '@meddleware/ui'
9
+ import {
10
+ CopyableAddress,
11
+ ExplorerLink,
12
+ suiExplorerUrl,
13
+ UiPanel,
14
+ UiStatGrid,
15
+ UiStatRow,
16
+ UiDataTable,
17
+ } from '@meddleware/ui'
12
18
  import { NETWORK } from '../config.js'
13
19
 
14
20
  const { config, loading: cfgLoading, error: cfgErr } = usePlatformConfig()
@@ -26,32 +32,27 @@ function formatPrice(mist: bigint): string {
26
32
  </script>
27
33
 
28
34
  <template>
29
- <div style="display: flex; flex-direction: column; gap: 10px">
30
- <Panel title="Treasury">
35
+ <div class="dao-stack">
36
+ <UiPanel title="Treasury">
31
37
  <p v-if="cfgLoading" class="dao-muted">Loading…</p>
32
38
  <p v-else-if="cfgErr" class="dao-muted">{{ cfgErr }}</p>
33
39
  <template v-else-if="config">
34
- <div class="dao-stat-grid" style="max-width: 480px">
35
- <span class="dao-stat-grid__label">Commission rate</span>
36
- <span class="dao-stat-grid__value dao-mono">{{ commissionPct }} ({{ config.commissionBps }} bps)</span>
37
-
38
- <span class="dao-stat-grid__label">Current balance</span>
39
- <AmountCell class="dao-stat-grid__value" :mist="balance" />
40
-
41
- <span class="dao-stat-grid__label">Treasury address</span>
42
- <span class="dao-stat-grid__value" style="text-align: left">
40
+ <UiStatGrid class="dao-stat-grid">
41
+ <UiStatRow label="Commission rate">{{ commissionPct }} ({{ config.commissionBps }} bps)</UiStatRow>
42
+ <UiStatRow label="Current balance"><AmountCell :mist="balance" /></UiStatRow>
43
+ <UiStatRow label="Treasury address" align="left">
43
44
  <CopyableAddress :address="config.treasury">
44
45
  <ExplorerLink :href="suiExplorerUrl('account', config.treasury, NETWORK)" :value="config.treasury" />
45
46
  </CopyableAddress>
46
- </span>
47
- </div>
47
+ </UiStatRow>
48
+ </UiStatGrid>
48
49
  </template>
49
50
  <p v-else class="dao-muted">PlatformConfig not loaded.</p>
50
- </Panel>
51
+ </UiPanel>
51
52
 
52
- <Panel title="Community Gates">
53
+ <UiPanel title="Community Gates">
53
54
  <p v-if="gatesLoading" class="dao-muted">Loading gates…</p>
54
- <DataTable v-else-if="gates.length" :empty="'No gates found'">
55
+ <UiDataTable v-else-if="gates.length" :empty="'No gates found'">
55
56
  <template #head>
56
57
  <th>Gate name</th>
57
58
  <th>Price</th>
@@ -60,14 +61,14 @@ function formatPrice(mist: bigint): string {
60
61
  <tr v-for="gate in gates" :key="gate.id">
61
62
  <td>{{ gate.name }}</td>
62
63
  <td class="dao-amount">{{ formatPrice(gate.price) }}</td>
63
- <td class="dao-mono" style="font-size: 0.7rem; white-space: nowrap">
64
+ <td class="dao-mono dao-mono--sm dao-nowrap">
64
65
  <CopyableAddress :address="gate.id" label="Copy object ID">
65
66
  <ExplorerLink :href="suiExplorerUrl('object', gate.id, NETWORK)" :value="gate.id" />
66
67
  </CopyableAddress>
67
68
  </td>
68
69
  </tr>
69
- </DataTable>
70
+ </UiDataTable>
70
71
  <p v-else class="dao-placeholder">No gates found.</p>
71
- </Panel>
72
+ </UiPanel>
72
73
  </div>
73
74
  </template>
@@ -1,26 +0,0 @@
1
- <script setup lang="ts">
2
- // Scrollable table shell with a `head` slot (header cells) and default slot (rows).
3
- // Renders the `empty` message when no rows are provided.
4
- defineProps<{ empty?: string }>()
5
-
6
- const slots = defineSlots<{
7
- head(): unknown
8
- default(): unknown
9
- }>()
10
- </script>
11
-
12
- <template>
13
- <div style="overflow-x: auto">
14
- <table class="dao-table">
15
- <thead>
16
- <tr>
17
- <slot name="head" />
18
- </tr>
19
- </thead>
20
- <tbody>
21
- <slot />
22
- </tbody>
23
- </table>
24
- <p v-if="empty && !slots.default" class="dao-placeholder">{{ empty }}</p>
25
- </div>
26
- </template>
@@ -1,13 +0,0 @@
1
- <script setup lang="ts">
2
- // Titled content panel — the console's basic surface primitive. Optional heading + default slot.
3
- defineProps<{ title?: string }>()
4
- </script>
5
-
6
- <template>
7
- <div class="dao-panel">
8
- <div v-if="title" class="dao-panel__head">{{ title }}</div>
9
- <div class="dao-panel__body">
10
- <slot />
11
- </div>
12
- </div>
13
- </template>
@@ -1,36 +0,0 @@
1
- <script setup lang="ts">
2
- // Bottom status bar: network + health dot (error-driven), current epoch, and a
3
- // relative "refreshed Ns ago" timestamp. Purely presentational.
4
- import { computed } from 'vue'
5
- import { NETWORK } from '../config.js'
6
-
7
- const props = defineProps<{
8
- epoch: number | null
9
- lastRefresh: Date | null
10
- error?: boolean
11
- }>()
12
-
13
- const dotClass = computed(() => (props.error ? 'dao-statusbar__dot--error' : 'dao-statusbar__dot--ok'))
14
-
15
- function timeAgo(d: Date): string {
16
- const s = Math.floor((Date.now() - d.getTime()) / 1000)
17
- if (s < 5) return 'just now'
18
- if (s < 60) return `${s}s ago`
19
- return `${Math.floor(s / 60)}m ago`
20
- }
21
- </script>
22
-
23
- <template>
24
- <footer class="dao-statusbar">
25
- <span class="dao-statusbar__item">
26
- <span class="dao-statusbar__dot" :class="dotClass" />
27
- {{ NETWORK.charAt(0).toUpperCase() + NETWORK.slice(1) }}
28
- </span>
29
- <span class="dao-statusbar__sep">│</span>
30
- <span v-if="epoch !== null" class="dao-statusbar__item">Epoch {{ epoch }}</span>
31
- <span v-else class="dao-statusbar__item dao-muted">Epoch —</span>
32
- <span class="dao-statusbar__sep">│</span>
33
- <span v-if="lastRefresh" class="dao-statusbar__item">Refreshed {{ timeAgo(lastRefresh) }}</span>
34
- <span v-else class="dao-statusbar__item dao-muted">Loading…</span>
35
- </footer>
36
- </template>
@@ -1,19 +0,0 @@
1
- <script setup lang="ts">
2
- // Thin wrapper over AppTabNav variant="raised" from @meddleware/ui.
3
- // Keeps dao-ui's internal import path stable while using the shared component.
4
- import { AppTabNav } from '@meddleware/ui'
5
- export type { AppTab as Tab } from '@meddleware/ui'
6
-
7
- defineProps<{ tabs: { id: string; label: string }[]; modelValue: string }>()
8
- const emit = defineEmits<{ 'update:modelValue': [id: string] }>()
9
- </script>
10
-
11
- <template>
12
- <AppTabNav
13
- :tabs="tabs"
14
- :model-value="modelValue"
15
- variant="raised"
16
- aria-label="DAO sections"
17
- @update:model-value="emit('update:modelValue', $event)"
18
- />
19
- </template>