picocrank 1.18.1 → 1.18.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picocrank",
3
- "version": "1.18.1",
3
+ "version": "1.18.2",
4
4
  "description": "A set of zero dependency Vue components built on the Femtocrank global CSS theme.",
5
5
  "main": "vite.config.js",
6
6
  "scripts": {
@@ -47,7 +47,10 @@ function addRouterLink(link, altTitle = null, options = {}) {
47
47
  icon: foundRoute.meta?.icon || PinIcon,
48
48
  type: 'route',
49
49
  props: options.props || {},
50
- description: options.description || foundRoute.meta?.description || null
50
+ description: options.description || foundRoute.meta?.description || null,
51
+ disabled: options.disabled || false,
52
+ iconColor: options.iconColor || null,
53
+ indicator: options.indicator || false
51
54
  }
52
55
 
53
56
  addNavigationLink(routeLink)
@@ -69,7 +72,10 @@ function addCallback(title, callback, options = {}) {
69
72
  icon: options.icon || PinIcon,
70
73
  callback: callback || (() => {}),
71
74
  title: title,
72
- description: options.description || null
75
+ description: options.description || null,
76
+ disabled: options.disabled || false,
77
+ iconColor: options.iconColor || null,
78
+ indicator: options.indicator || false
73
79
  }
74
80
 
75
81
  addNavigationLink(callbackLink)
@@ -4,11 +4,17 @@
4
4
  <button
5
5
  v-for="link in filteredLinks"
6
6
  :key="link.name"
7
- :class="['nav-button', { active: isLinkActive(link) }]"
7
+ :class="['nav-button', { active: isLinkActive(link), disabled: link.disabled }]"
8
+ :disabled="link.disabled"
8
9
  :title="link.title"
9
10
  @click="handleLinkClick(link)"
10
11
  >
11
- <div class="nav-button-icon">
12
+ <span
13
+ v-if="showIndicator(link)"
14
+ class="nav-button-indicator"
15
+ aria-label="Requires attention"
16
+ />
17
+ <div class="nav-button-icon" :style="getIconStyle(link)">
12
18
  <HugeiconsIcon
13
19
  :icon="link.icon"
14
20
  :width="iconSize"
@@ -102,10 +108,30 @@ const filteredLinks = computed(() => {
102
108
  });
103
109
 
104
110
  function isLinkActive(link) {
111
+ if (link.disabled) {
112
+ return false;
113
+ }
105
114
  return isActive(link);
106
115
  }
107
116
 
117
+ function getIconStyle(link) {
118
+ if (link.disabled || isLinkActive(link)) {
119
+ return undefined;
120
+ }
121
+ if (link.iconColor) {
122
+ return { color: link.iconColor };
123
+ }
124
+ return undefined;
125
+ }
126
+
127
+ function showIndicator(link) {
128
+ return link.indicator && !link.disabled;
129
+ }
130
+
108
131
  function handleLinkClick(link) {
132
+ if (link.disabled) {
133
+ return;
134
+ }
109
135
  if (link.type === 'route') {
110
136
  const to = link.to || link.path;
111
137
  if (to) {
@@ -147,6 +173,7 @@ function handleLinkClick(link) {
147
173
  cursor: pointer;
148
174
  transition: all 0.2s ease;
149
175
  text-align: left;
176
+ position: relative;
150
177
  }
151
178
 
152
179
  .navigation-grid.compact .nav-button {
@@ -188,6 +215,46 @@ function handleLinkClick(link) {
188
215
  color: #fff;
189
216
  }
190
217
 
218
+ .nav-button:disabled,
219
+ .nav-button.disabled {
220
+ cursor: not-allowed;
221
+ opacity: 0.6;
222
+ }
223
+
224
+ .nav-button:disabled:hover,
225
+ .nav-button.disabled:hover {
226
+ border-color: var(--border-color, #e1e5e9);
227
+ transform: none;
228
+ box-shadow: none;
229
+ background: transparent;
230
+ }
231
+
232
+ .nav-button:disabled .nav-button-icon,
233
+ .nav-button.disabled .nav-button-icon {
234
+ color: var(--text-muted, #999);
235
+ }
236
+
237
+ .nav-button-indicator {
238
+ position: absolute;
239
+ top: 0.75rem;
240
+ right: 0.75rem;
241
+ width: 0.625rem;
242
+ height: 0.625rem;
243
+ border-radius: 50%;
244
+ background: var(--indicator-color, #dc3545);
245
+ box-shadow: 0 0 0 2px var(--background-color, #fff);
246
+ flex-shrink: 0;
247
+ }
248
+
249
+ .navigation-grid.compact .nav-button-indicator {
250
+ top: 0.5rem;
251
+ right: 0.5rem;
252
+ }
253
+
254
+ .nav-button.active .nav-button-indicator {
255
+ box-shadow: 0 0 0 2px var(--primary-color, #007bff);
256
+ }
257
+
191
258
  .nav-button-label {
192
259
  font-weight: bold;
193
260
  font-size: 1.125rem;
@@ -60,7 +60,9 @@ onMounted(() => {
60
60
  }, {
61
61
  icon: ViewIcon,
62
62
  name: 'notifications',
63
- description: 'Manage notification settings'
63
+ description: 'Manage notification settings',
64
+ iconColor: '#e67e22',
65
+ indicator: true
64
66
  });
65
67
 
66
68
  localNavigation.value.addCallback('Billing', () => {
@@ -68,7 +70,8 @@ onMounted(() => {
68
70
  }, {
69
71
  icon: EditIcon,
70
72
  name: 'billing',
71
- description: 'View billing and subscription details'
73
+ description: 'View billing and subscription details',
74
+ disabled: true
72
75
  });
73
76
  }
74
77
  });