@lowdefy/blocks-antd 5.1.0 → 5.2.0

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.
@@ -15,10 +15,11 @@
15
15
  */ import React, { useEffect } from 'react';
16
16
  import { get } from '@lowdefy/helpers';
17
17
  import { List, Typography } from 'antd';
18
- import { withBlockDefaults } from '@lowdefy/block-utils';
18
+ import { cn, withBlockDefaults } from '@lowdefy/block-utils';
19
19
  import Button from '../Button/Button.js';
20
20
  import withTheme from '../withTheme.js';
21
- const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Link, ShortcutBadge }, events, list, methods, properties, styles = {} })=>{
21
+ import './style.module.css';
22
+ const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Link, ShortcutBadge }, events, list, methods, properties, styles = {}, value = [] })=>{
22
23
  useEffect(()=>{
23
24
  methods.registerMethod('moveItemDown', methods.moveItemDown);
24
25
  methods.registerMethod('moveItemUp', methods.moveItemUp);
@@ -31,6 +32,38 @@ const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Lin
31
32
  methods.pushItem({});
32
33
  }
33
34
  }
35
+ const addItemToFront = ()=>{
36
+ methods.unshiftItem();
37
+ methods.triggerEvent({
38
+ name: 'onAdd',
39
+ event: {
40
+ index: 0,
41
+ item: undefined
42
+ }
43
+ });
44
+ };
45
+ const addItemToBack = ()=>{
46
+ const index = value.length;
47
+ methods.pushItem();
48
+ methods.triggerEvent({
49
+ name: 'onAdd',
50
+ event: {
51
+ index,
52
+ item: undefined
53
+ }
54
+ });
55
+ };
56
+ const removeItemAt = (index)=>{
57
+ const item = value[index];
58
+ methods.removeItem(index);
59
+ methods.triggerEvent({
60
+ name: 'onRemove',
61
+ event: {
62
+ index,
63
+ item
64
+ }
65
+ });
66
+ };
34
67
  return /*#__PURE__*/ React.createElement(List, {
35
68
  id: blockId,
36
69
  className: classNames.element,
@@ -61,7 +94,7 @@ const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Lin
61
94
  type: 'default',
62
95
  ...properties.addItemButton
63
96
  },
64
- onClick: ()=>methods.unshiftItem()
97
+ onClick: addItemToFront
65
98
  })),
66
99
  footer: !properties.addToFront && !properties.hideAddButton && /*#__PURE__*/ React.createElement("div", {
67
100
  style: {
@@ -86,7 +119,7 @@ const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Lin
86
119
  type: 'dashed',
87
120
  ...properties.addItemButton
88
121
  },
89
- onClick: ()=>methods.pushItem()
122
+ onClick: addItemToBack
90
123
  })),
91
124
  bordered: true,
92
125
  locale: {
@@ -102,24 +135,16 @@ const ControlledListBlock = ({ blockId, classNames = {}, components: { Icon, Lin
102
135
  extra: !properties.hideRemoveButton && list.length > (properties.minItems ?? 0) && [
103
136
  // eslint-disable-next-line react/jsx-key
104
137
  /*#__PURE__*/ React.createElement("span", {
105
- style: {
106
- paddingLeft: properties.size === 'small' ? 2 : properties.size === 'large' ? 6 : 4,
107
- fontSize: properties.size === 'small' ? 16 : properties.size === 'large' ? 20 : 18
108
- }
138
+ className: cn('lf-controlled-list-remove', classNames.removeIcon),
139
+ style: styles.removeIcon
109
140
  }, /*#__PURE__*/ React.createElement(Icon, {
110
141
  blockId: `${blockId}_${i}_remove_icon`,
111
- classNames: {
112
- element: classNames.removeIcon
113
- },
114
142
  events: events,
115
143
  properties: {
116
144
  name: 'AiOutlineMinusCircle',
117
145
  ...properties.removeItemIcon
118
146
  },
119
- styles: {
120
- element: styles.removeIcon
121
- },
122
- onClick: ()=>methods.removeItem(i)
147
+ onClick: ()=>removeItemAt(i)
123
148
  }))
124
149
  ]
125
150
  }, item.content && item.content({
@@ -22,12 +22,16 @@
22
22
  slots: {
23
23
  content: 'Blocks rendered for each list item.'
24
24
  },
25
+ events: {
26
+ onAdd: 'Triggered after a new item is added via the add button. The event payload is `{ index, item }`, where `item` is the newly added value (`undefined` for an empty row).',
27
+ onRemove: 'Triggered after an item is removed via the remove icon. The event payload is `{ index, item }`, where `item` is the removed value captured before removal.'
28
+ },
25
29
  cssKeys: {
26
30
  element: 'The ControlledList element.',
27
31
  header: 'The ControlledList header.',
28
32
  footer: 'The ControlledList footer.',
29
33
  item: 'The ControlledList item.',
30
- removeIcon: 'The remove item icon in the ControlledList.'
34
+ removeIcon: 'The remove-item icon wrapper. Defaults to the antd error color at `fontSizeLG`; override `color`, `font-size`, or spacing here.'
31
35
  },
32
36
  properties: {
33
37
  type: 'object',
@@ -69,7 +73,7 @@
69
73
  'string',
70
74
  'object'
71
75
  ],
72
- description: 'Custom remove item icon properties.',
76
+ description: 'Custom remove item icon properties. Defaults to `AiOutlineMinusCircle` at a standard size with the antd error color inherited from the icon wrapper — override via `class.removeIcon` / `style.removeIcon` for visual tweaks, or via this property to change the icon name itself.',
73
77
  docs: {
74
78
  displayType: 'icon'
75
79
  }
@@ -0,0 +1,35 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ @layer components {
18
+ :global(.lf-controlled-list-remove) {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ padding-left: var(--ant-padding-xs);
22
+ font-size: var(--ant-font-size-lg);
23
+ color: var(--ant-color-error);
24
+ cursor: pointer;
25
+ transition: color 0.2s;
26
+ }
27
+
28
+ :global(.lf-controlled-list-remove:hover) {
29
+ color: var(--ant-color-error-hover);
30
+ }
31
+
32
+ :global(.lf-controlled-list-remove:active) {
33
+ color: var(--ant-color-error-active);
34
+ }
35
+ }
@@ -62,10 +62,12 @@ function DropdownButtonBlock({ blockId, classNames = {}, components: { Icon, Sho
62
62
  key: `divider-${i}`
63
63
  };
64
64
  }
65
+ const eventShortcut = item.eventName ? events[item.eventName]?.shortcut : undefined;
66
+ const itemShortcut = eventShortcut ?? item.shortcut;
65
67
  return {
66
68
  key: item.eventName ?? `item-${i}`,
67
- label: /*#__PURE__*/ React.createElement("span", null, item.title, item.shortcut && /*#__PURE__*/ React.createElement(ShortcutBadge, {
68
- shortcut: item.shortcut
69
+ label: /*#__PURE__*/ React.createElement("span", null, item.title, itemShortcut && /*#__PURE__*/ React.createElement(ShortcutBadge, {
70
+ shortcut: itemShortcut
69
71
  })),
70
72
  icon: item.icon ? /*#__PURE__*/ React.createElement(Icon, {
71
73
  blockId: `${blockId}_icon_${i}`,
@@ -82,7 +84,10 @@ function DropdownButtonBlock({ blockId, classNames = {}, components: { Icon, Sho
82
84
  disabled: item.disabled
83
85
  };
84
86
  });
85
- const shortcutItems = (properties.items ?? []).filter((item)=>item.shortcut && item.eventName && !item.disabled).map((item)=>({
87
+ // Item-level shortcut fallback for items that declare `shortcut` on properties
88
+ // rather than via `events.<eventName>.shortcut`. Skip items whose event already
89
+ // owns the shortcut — the framework-level shortcut manager handles those.
90
+ const propertyShortcutItems = (properties.items ?? []).filter((item)=>item.shortcut && item.eventName && !item.disabled && !events[item.eventName]?.shortcut).map((item)=>({
86
91
  key: item.eventName,
87
92
  shortcut: item.shortcut
88
93
  }));
@@ -94,12 +99,13 @@ function DropdownButtonBlock({ blockId, classNames = {}, components: { Icon, Sho
94
99
  methods
95
100
  ]);
96
101
  useItemShortcuts({
97
- items: shortcutItems,
102
+ items: propertyShortcutItems,
98
103
  onMatch: onShortcutMatch
99
104
  });
100
105
  const onClickActionName = get(rename, 'events.onClick', {
101
106
  default: 'onClick'
102
107
  });
108
+ const onClickShortcut = events[onClickActionName]?.shortcut;
103
109
  const dropdownProps = {
104
110
  menu: {
105
111
  items,
@@ -162,7 +168,9 @@ function DropdownButtonBlock({ blockId, classNames = {}, components: { Icon, Sho
162
168
  onClick: ()=>methods.triggerEvent({
163
169
  name: onClickActionName
164
170
  })
165
- }, properties.title), /*#__PURE__*/ React.createElement(Dropdown, dropdownProps, /*#__PURE__*/ React.createElement(Button, {
171
+ }, properties.title, onClickShortcut && /*#__PURE__*/ React.createElement(ShortcutBadge, {
172
+ shortcut: onClickShortcut
173
+ })), /*#__PURE__*/ React.createElement(Dropdown, dropdownProps, /*#__PURE__*/ React.createElement(Button, {
166
174
  color: resolvedColor,
167
175
  variant: variant,
168
176
  type: buttonType,
@@ -26,7 +26,7 @@
26
26
  arrow: 'Dropdown arrow indicator.'
27
27
  },
28
28
  events: {
29
- onClick: 'Trigger action when the button is clicked (split mode).',
29
+ onClick: 'Trigger action when the button is clicked (split mode). Renders a shortcut badge when a shortcut is configured on the event.',
30
30
  onOpenChange: 'Trigger action when dropdown opens or closes.'
31
31
  },
32
32
  properties: {
@@ -162,7 +162,7 @@
162
162
  },
163
163
  items: {
164
164
  type: 'array',
165
- description: 'Menu items. Each with an eventName that triggers a named event.',
165
+ description: 'Menu items. Each with an eventName that triggers a named event. Keyboard shortcuts can be configured via the standard `events.<eventName>.shortcut` schema (preferred) or via the item-level `shortcut` property — both render a badge next to the item label. The event-level shortcut takes precedence when both are set.',
166
166
  items: {
167
167
  type: 'object',
168
168
  properties: {
@@ -201,7 +201,7 @@
201
201
  },
202
202
  shortcut: {
203
203
  type: 'string',
204
- description: 'Keyboard shortcut. Binds the key and renders the badge.'
204
+ description: 'Keyboard shortcut. Binds the key and renders the badge. Prefer configuring this via `events.<eventName>.shortcut` to follow the standard Lowdefy event schema — the event-level shortcut takes precedence when both are set.'
205
205
  }
206
206
  }
207
207
  }
@@ -126,7 +126,11 @@ const PageSidebarLayout = ({ basePath, blockId, classNames = {}, components: { I
126
126
  styles: {
127
127
  element: mergeObjects([
128
128
  {
129
- borderInlineEnd: '1px solid var(--ant-color-border)'
129
+ borderInlineEnd: '1px solid var(--ant-color-border)',
130
+ position: 'sticky',
131
+ top: 0,
132
+ height: '100vh',
133
+ alignSelf: 'flex-start'
130
134
  },
131
135
  styles.sider
132
136
  ])
@@ -231,17 +235,18 @@ const PageSidebarLayout = ({ basePath, blockId, classNames = {}, components: { I
231
235
  style: {
232
236
  position: 'sticky',
233
237
  bottom: 0,
234
- background: 'var(--ant-color-bg-container)',
235
- padding: 8,
238
+ background: 'linear-gradient(to bottom, transparent 0%, color-mix(in srgb, var(--ant-color-bg-container) 85%, transparent) 32px, color-mix(in srgb, var(--ant-color-bg-container) 95%, transparent) 100%)',
239
+ padding: '40px 8px 8px',
236
240
  display: 'flex',
237
241
  flexDirection: 'column',
238
- alignItems: 'center'
242
+ alignItems: 'center',
243
+ gap: 8
239
244
  }
240
245
  }, renderHeaderActions({
241
246
  blockId,
242
247
  classNames: {
243
248
  ...classNames,
244
- headerActions: classNames.headerActions ?? 'flex flex-col items-center gap-4 py-4'
249
+ headerActions: classNames.headerActions ?? (openSiderState ? 'flex flex-col items-stretch gap-1 w-full' : 'flex flex-col items-center gap-4 py-4')
245
250
  },
246
251
  styles,
247
252
  properties,
@@ -252,7 +257,8 @@ const PageSidebarLayout = ({ basePath, blockId, classNames = {}, components: { I
252
257
  Link,
253
258
  ShortcutBadge
254
259
  },
255
- iconsColor: properties.iconsColor
260
+ iconsColor: properties.iconsColor,
261
+ expanded: openSiderState
256
262
  }), /*#__PURE__*/ React.createElement(Link, {
257
263
  home: true
258
264
  }, /*#__PURE__*/ React.createElement("img", {
@@ -255,6 +255,11 @@ export default {
255
255
  description: 'Notification bell icon with badge. Shown in the sider on desktop and the mobile header on small screens. Renders when configured. Use the link property to navigate when clicked.',
256
256
  additionalProperties: false,
257
257
  properties: {
258
+ title: {
259
+ type: 'string',
260
+ default: 'Notifications',
261
+ description: 'Label shown next to the bell icon when the sider is expanded. Hidden on mobile header and collapsed sider.'
262
+ },
258
263
  link: {
259
264
  type: 'object',
260
265
  description: 'Link to navigate to when the notification bell is clicked.',
@@ -321,6 +326,11 @@ export default {
321
326
  description: 'Profile avatar with optional dropdown menu. Shown in the sider on desktop and the mobile header on small screens. Renders when configured. Use with the _user operator to populate from the authenticated user.',
322
327
  additionalProperties: false,
323
328
  properties: {
329
+ title: {
330
+ type: 'string',
331
+ default: 'Profile',
332
+ description: 'Label shown next to the avatar when the sider is expanded. Hidden on mobile header and collapsed sider.'
333
+ },
324
334
  avatar: {
325
335
  type: 'object',
326
336
  description: 'Avatar display properties.',
@@ -28,7 +28,73 @@ function getDarkModeIcon() {
28
28
  if (pref === 'light') return 'AiOutlineSun';
29
29
  return 'AiOutlineLaptop';
30
30
  }
31
- function renderNotifications({ blockId, classNames, styles, properties, events, Icon, Link, iconsColor }) {
31
+ function getDarkModeLabel() {
32
+ const pref = getDarkModePreference();
33
+ if (pref === 'dark') return 'Dark mode';
34
+ if (pref === 'light') return 'Light mode';
35
+ return 'System';
36
+ }
37
+ // Wraps a header action row for the expanded sider. Icon cell has a fixed
38
+ // basis so bell / avatar / sun share a vertical line regardless of their
39
+ // own intrinsic size; label fills the remaining width. Row gets a subtle
40
+ // hover background so it reads as interactive (matches menu items above).
41
+ const EXPANDED_ROW_BASE = {
42
+ display: 'flex',
43
+ alignItems: 'center',
44
+ gap: 12,
45
+ padding: '8px 12px',
46
+ width: '100%',
47
+ borderRadius: 6,
48
+ transition: 'background 0.15s'
49
+ };
50
+ const EXPANDED_ROW_BUTTON_RESET = {
51
+ background: 'transparent',
52
+ border: 'none',
53
+ textAlign: 'left',
54
+ font: 'inherit',
55
+ color: 'inherit'
56
+ };
57
+ function ExpandedRow({ children, label, className, style, onClick }) {
58
+ // `onClick` is only used when the row stands alone as the click target
59
+ // (e.g., dark-mode toggle). Notifications wraps this in a <Link> and
60
+ // profile wraps it in a <Dropdown> — in those cases interactivity comes
61
+ // from the parent, but the row should still hover-highlight.
62
+ const Tag = onClick ? 'button' : 'div';
63
+ const [hover, setHover] = React.useState(false);
64
+ const rowStyle = {
65
+ ...EXPANDED_ROW_BASE,
66
+ cursor: 'pointer',
67
+ ...onClick ? EXPANDED_ROW_BUTTON_RESET : null,
68
+ ...hover ? {
69
+ background: 'color-mix(in srgb, var(--ant-color-text) 6%, transparent)'
70
+ } : null,
71
+ ...style
72
+ };
73
+ return /*#__PURE__*/ React.createElement(Tag, {
74
+ type: onClick ? 'button' : undefined,
75
+ className: className,
76
+ style: rowStyle,
77
+ onClick: onClick,
78
+ onMouseEnter: ()=>setHover(true),
79
+ onMouseLeave: ()=>setHover(false)
80
+ }, /*#__PURE__*/ React.createElement("span", {
81
+ style: {
82
+ display: 'inline-flex',
83
+ alignItems: 'center',
84
+ justifyContent: 'center',
85
+ flex: '0 0 24px',
86
+ lineHeight: 1
87
+ }
88
+ }, children), /*#__PURE__*/ React.createElement("span", {
89
+ style: {
90
+ flex: 1,
91
+ minWidth: 0,
92
+ overflow: 'hidden',
93
+ textOverflow: 'ellipsis'
94
+ }
95
+ }, label));
96
+ }
97
+ function renderNotifications({ blockId, classNames, styles, properties, events, Icon, Link, iconsColor, expanded }) {
32
98
  if (type.isNone(properties.notifications)) return null;
33
99
  const notif = properties.notifications;
34
100
  const badge = /*#__PURE__*/ React.createElement(Badge, {
@@ -55,6 +121,26 @@ function renderNotifications({ blockId, classNames, styles, properties, events,
55
121
  }
56
122
  }));
57
123
  const link = notif.link;
124
+ if (expanded) {
125
+ const row = /*#__PURE__*/ React.createElement(ExpandedRow, {
126
+ className: classNames.notifications,
127
+ style: styles.notifications,
128
+ label: notif.title ?? 'Notifications'
129
+ }, badge);
130
+ if (link) {
131
+ return /*#__PURE__*/ React.createElement(Link, {
132
+ id: `${blockId}_notifications_link`,
133
+ pageId: link.pageId,
134
+ url: link.url,
135
+ newTab: link.newTab,
136
+ style: {
137
+ display: 'block',
138
+ color: 'inherit'
139
+ }
140
+ }, row);
141
+ }
142
+ return row;
143
+ }
58
144
  if (link) {
59
145
  return /*#__PURE__*/ React.createElement(Link, {
60
146
  id: `${blockId}_notifications_link`,
@@ -76,7 +162,7 @@ function renderNotifications({ blockId, classNames, styles, properties, events,
76
162
  }
77
163
  }, badge);
78
164
  }
79
- function renderProfile({ blockId, classNames, styles, properties, methods, events, Icon, Link, ShortcutBadge }) {
165
+ function renderProfile({ blockId, classNames, styles, properties, methods, events, Icon, Link, ShortcutBadge, expanded }) {
80
166
  if (type.isNone(properties.profile)) return null;
81
167
  const prof = properties.profile;
82
168
  const avatarProps = prof.avatar ?? {};
@@ -99,12 +185,17 @@ function renderProfile({ blockId, classNames, styles, properties, methods, event
99
185
  }
100
186
  })
101
187
  }, avatarProps.content);
188
+ const trigger = expanded ? /*#__PURE__*/ React.createElement(ExpandedRow, {
189
+ className: classNames.profile,
190
+ style: styles.profile,
191
+ label: prof.title ?? 'Profile'
192
+ }, avatar) : /*#__PURE__*/ React.createElement("div", {
193
+ className: classNames.profile,
194
+ style: styles.profile
195
+ }, avatar);
102
196
  const links = prof.links ?? [];
103
197
  if (links.length === 0) {
104
- return /*#__PURE__*/ React.createElement("div", {
105
- className: classNames.profile,
106
- style: styles.profile
107
- }, avatar);
198
+ return trigger;
108
199
  }
109
200
  const items = buildMenuItems({
110
201
  links,
@@ -119,10 +210,8 @@ function renderProfile({ blockId, classNames, styles, properties, methods, event
119
210
  });
120
211
  const linkMap = flattenLinks(links);
121
212
  return /*#__PURE__*/ React.createElement(Dropdown, {
122
- className: classNames.profile,
123
213
  style: {
124
- cursor: 'pointer',
125
- ...styles.profile
214
+ cursor: 'pointer'
126
215
  },
127
216
  menu: {
128
217
  items,
@@ -139,10 +228,11 @@ function renderProfile({ blockId, classNames, styles, properties, methods, event
139
228
  });
140
229
  }
141
230
  },
231
+ // Row-style trigger (expanded) expects click; small avatar (collapsed) uses hover.
142
232
  trigger: [
143
- prof.trigger ?? 'hover'
233
+ prof.trigger ?? (expanded ? 'click' : 'hover')
144
234
  ],
145
- placement: prof.placement ?? 'bottomRight',
235
+ placement: prof.placement ?? (expanded ? 'topRight' : 'bottomRight'),
146
236
  arrow: prof.arrow,
147
237
  popupClassName: classNames.profileMenu,
148
238
  popupStyle: styles.profileMenu,
@@ -152,20 +242,10 @@ function renderProfile({ blockId, classNames, styles, properties, methods, event
152
242
  open
153
243
  }
154
244
  })
155
- }, /*#__PURE__*/ React.createElement("div", null, avatar));
245
+ }, /*#__PURE__*/ React.createElement("div", null, trigger));
156
246
  }
157
- function renderDarkModeToggle({ blockId, classNames, styles, methods, events, Icon, iconsColor }) {
158
- return /*#__PURE__*/ React.createElement("div", {
159
- className: classNames.darkModeToggle,
160
- style: {
161
- cursor: 'pointer',
162
- lineHeight: 1,
163
- ...styles.darkModeToggle
164
- },
165
- onClick: ()=>methods.triggerEvent({
166
- name: '__toggleDarkMode'
167
- })
168
- }, /*#__PURE__*/ React.createElement(Icon, {
247
+ function renderDarkModeToggle({ blockId, classNames, styles, methods, events, Icon, iconsColor, expanded }) {
248
+ const icon = /*#__PURE__*/ React.createElement(Icon, {
169
249
  blockId: `${blockId}_dark_mode_toggle_icon`,
170
250
  events: events,
171
251
  properties: {
@@ -177,9 +257,30 @@ function renderDarkModeToggle({ blockId, classNames, styles, methods, events, Ic
177
257
  color: iconsColor
178
258
  }
179
259
  }
180
- }));
260
+ });
261
+ if (expanded) {
262
+ return /*#__PURE__*/ React.createElement(ExpandedRow, {
263
+ className: classNames.darkModeToggle,
264
+ style: styles.darkModeToggle,
265
+ label: getDarkModeLabel(),
266
+ onClick: ()=>methods.triggerEvent({
267
+ name: '__toggleDarkMode'
268
+ })
269
+ }, icon);
270
+ }
271
+ return /*#__PURE__*/ React.createElement("div", {
272
+ className: classNames.darkModeToggle,
273
+ style: {
274
+ cursor: 'pointer',
275
+ lineHeight: 1,
276
+ ...styles.darkModeToggle
277
+ },
278
+ onClick: ()=>methods.triggerEvent({
279
+ name: '__toggleDarkMode'
280
+ })
281
+ }, icon);
181
282
  }
182
- function renderHeaderActions({ blockId, classNames = {}, styles = {}, properties, methods, events, components: { Icon, Link, ShortcutBadge }, iconsColor }) {
283
+ function renderHeaderActions({ blockId, classNames = {}, styles = {}, properties, methods, events, components: { Icon, Link, ShortcutBadge }, iconsColor, expanded = false }) {
183
284
  const hasNotifications = !type.isNone(properties.notifications);
184
285
  const hasProfile = !type.isNone(properties.profile);
185
286
  const hasDarkMode = properties.darkModeToggle;
@@ -194,10 +295,12 @@ function renderHeaderActions({ blockId, classNames = {}, styles = {}, properties
194
295
  Icon,
195
296
  Link,
196
297
  ShortcutBadge,
197
- iconsColor
298
+ iconsColor,
299
+ expanded
198
300
  };
301
+ const defaultClassName = expanded ? 'flex flex-col items-stretch gap-1 w-full' : 'flex items-center gap-4 ml-4';
199
302
  return /*#__PURE__*/ React.createElement("div", {
200
- className: classNames.headerActions ?? 'flex items-center gap-4 ml-4',
303
+ className: classNames.headerActions ?? defaultClassName,
201
304
  style: styles.headerActions
202
305
  }, hasNotifications && renderNotifications(ctx), hasProfile && renderProfile(ctx), hasDarkMode && renderDarkModeToggle(ctx));
203
306
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/blocks-antd",
3
- "version": "5.1.0",
3
+ "version": "5.2.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lowdefy Ant Design Blocks",
6
6
  "homepage": "https://lowdefy.com",
@@ -45,8 +45,8 @@
45
45
  ],
46
46
  "dependencies": {
47
47
  "@ant-design/icons": "6.1.0",
48
- "@lowdefy/block-utils": "5.1.0",
49
- "@lowdefy/helpers": "5.1.0",
48
+ "@lowdefy/block-utils": "5.2.0",
49
+ "@lowdefy/helpers": "5.2.0",
50
50
  "@rc-component/motion": "1.3.1",
51
51
  "classnames": "2.3.2",
52
52
  "dayjs": "1.11.19",
@@ -58,9 +58,9 @@
58
58
  "react-dom": ">=18"
59
59
  },
60
60
  "devDependencies": {
61
- "@lowdefy/block-dev-e2e": "5.1.0",
62
- "@lowdefy/e2e-utils": "5.1.0",
63
- "@lowdefy/node-utils": "5.1.0",
61
+ "@lowdefy/block-dev-e2e": "5.2.0",
62
+ "@lowdefy/e2e-utils": "5.2.0",
63
+ "@lowdefy/node-utils": "5.2.0",
64
64
  "@playwright/test": "1.50.1",
65
65
  "@swc/cli": "0.8.0",
66
66
  "@swc/core": "1.15.18",