@nkootstra/block-kit 0.1.1 → 0.3.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.
- package/README.md +3 -3
- package/dist/{index-FPjJcmn3.d.ts → index-D139DZfD.d.ts} +34 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +95 -32
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -4820
- package/dist/styles.css.map +1 -0
- package/dist/transport.d.ts +1 -1
- package/dist/web-api.d.ts +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
`@nkootstra/block-kit` renders Slack [Block Kit](https://docs.slack.dev/block-kit/) JSON in React, pixel-for-pixel the way Slack does. Pass it the `blocks` your app sends to `chat.postMessage` or `views.open` and it draws the message, modal or Home tab, with working buttons, menus, date pickers and inputs.
|
|
4
4
|
|
|
5
|
-
Documentation: **<https://block-kit.
|
|
5
|
+
Documentation: **<https://docs.block-kit.dev>**
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
|
-
The package needs React
|
|
9
|
+
The package needs React 18 or later.
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
bun add @nkootstra/block-kit @fontsource/lato @fontsource/roboto-mono
|
|
@@ -33,7 +33,7 @@ export function App() {
|
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The [installation guide](https://block-kit.
|
|
36
|
+
The [installation guide](https://docs.block-kit.dev/installation) lists the remaining font weights and the entry points, and the [quickstart](https://docs.block-kit.dev/quickstart) wires up an interactive approval message.
|
|
37
37
|
|
|
38
38
|
## Entry points
|
|
39
39
|
|
|
@@ -580,6 +580,20 @@ interface PayloadContext {
|
|
|
580
580
|
}
|
|
581
581
|
/** What `onSubmit` may return: Slack's `response_action` ack, or nothing to just close the modal. */
|
|
582
582
|
type SubmitResult = ViewResponseAction | undefined | void;
|
|
583
|
+
/** What block-kit passes to a `linkComponent`: an anchor's props, ready to spread. */
|
|
584
|
+
interface LinkProps {
|
|
585
|
+
href: string;
|
|
586
|
+
className?: string;
|
|
587
|
+
target?: string;
|
|
588
|
+
rel?: string;
|
|
589
|
+
children?: ReactNode;
|
|
590
|
+
}
|
|
591
|
+
/** A resolved mention, as `mentionHref` gets it. */
|
|
592
|
+
interface MentionRef {
|
|
593
|
+
type: "user" | "channel" | "usergroup";
|
|
594
|
+
/** Slack id, e.g. `U0123ABC`, `C0123ABC` or `S0123ABC`. */
|
|
595
|
+
id: string;
|
|
596
|
+
}
|
|
583
597
|
interface BlockKitContextValue {
|
|
584
598
|
surface: Surface;
|
|
585
599
|
/** The provider's `theme`. Popovers, tooltips and dialogs render outside its wrapper, so they set it themselves. */
|
|
@@ -594,6 +608,10 @@ interface BlockKitContextValue {
|
|
|
594
608
|
/** Called with a `view_closed` payload when a `<Modal>`'s close (X) button is pressed. */
|
|
595
609
|
onClose?: (payload: ReturnType<typeof buildViewClosedPayload>) => void;
|
|
596
610
|
resolvers: Resolvers;
|
|
611
|
+
/** Renders links from the payload; an `<a>` unless the provider's `linkComponent` says otherwise. */
|
|
612
|
+
linkComponent?: ComponentType<LinkProps>;
|
|
613
|
+
/** The app's page for a mention, if it has one. */
|
|
614
|
+
mentionHref?: (mention: MentionRef) => string | undefined;
|
|
597
615
|
emoji: EmojiOptions;
|
|
598
616
|
/** Validation errors keyed by block_id, as returned in `response_action: "errors"`. */
|
|
599
617
|
errors: Record<string, string>;
|
|
@@ -656,6 +674,20 @@ interface BlockKitProviderProps {
|
|
|
656
674
|
/** Called whenever an input value changes, with the full `state.values`. */
|
|
657
675
|
onStateChange?: (state: StateValues) => void;
|
|
658
676
|
resolvers?: Resolvers;
|
|
677
|
+
/**
|
|
678
|
+
* Renders every link that comes from the payload, e.g. a router's `<Link>` for client-side
|
|
679
|
+
* navigation or a component that rewrites URLs: links in mrkdwn, rich text, markdown and dates,
|
|
680
|
+
* data tables, plan and task card sources, video titles, attachment authors and titles, and
|
|
681
|
+
* mentions linked by `mentionHref`. It gets an anchor's props to spread: `href`, `className`,
|
|
682
|
+
* `children`, and `target`/`rel` for links that open a new tab, as Slack's do.
|
|
683
|
+
*/
|
|
684
|
+
linkComponent?: ComponentType<LinkProps>;
|
|
685
|
+
/**
|
|
686
|
+
* Links resolved mentions to the app's own pages: return a URL for a user, channel or user
|
|
687
|
+
* group, or `undefined` to leave it unlinked. Mention links open in the same tab and render
|
|
688
|
+
* through `linkComponent`.
|
|
689
|
+
*/
|
|
690
|
+
mentionHref?: (mention: MentionRef) => string | undefined;
|
|
659
691
|
emoji?: EmojiOptions;
|
|
660
692
|
errors?: Record<string, string>;
|
|
661
693
|
timeZone?: string;
|
|
@@ -907,5 +939,5 @@ declare const VALIDATION_MESSAGES: {
|
|
|
907
939
|
*/
|
|
908
940
|
declare function validateView(blocks: readonly Json[] | readonly unknown[], state: StateValues): Record<string, string>;
|
|
909
941
|
//#endregion
|
|
910
|
-
export {
|
|
911
|
-
//# sourceMappingURL=index-
|
|
942
|
+
export { useLiveView as $, BlockAction as A, PayloadContext as B, SlackAttachment as C, Block as Ct, elementComponents as D, Json as Dt, SlackReaction as E, ElementProps as Et, EmojiOptions as F, Surface as G, StackedView as H, LinkProps as I, SurfaceScopeValue as J, SurfaceScope as K, MentionRef as L, BlockKitProvider as M, BlockKitProviderProps as N, Element as O, ElementState as P, useContainer as Q, MessageApi as R, MessageProps as S, blockComponents as St, SlackMessageLike as T, BlockProps as Tt, StateValues as U, Resolvers as V, SubmitResult as W, ViewsApi as X, UserProfile as Y, useBlockKit as Z, HomeTabView as _, ViewResponseAction as _t, Tooltip as a, BuildViewSubmissionPayloadOptions as at, Message as b, buildViewClosedPayload as bt, TextObject as c, MessageContainer as ct, ViewProps as d, PayloadTeam as dt, BlockActionsPayload as et, Modal as f, PayloadUser as ft, HomeTabProps as g, ViewLike as gt, HomeTab as h, ViewContainer as ht, UserMentionProps as i, BuildViewClosedPayloadOptions as it, BlockKitContextValue as j, ActionContext as k, AnyView as l, OptionsResponse as lt, ModalView as m, ViewBlockActionsPayload as mt, validateView as n, BuildBlockActionsPayloadOptions as nt, TooltipProps as o, Container as ot, ModalProps as p, SuggestionOption as pt, SurfaceScopeProps as q, UserMention as r, BuildBlockSuggestionPayloadOptions as rt, Text as s, MessageBlockActionsPayload as st, VALIDATION_MESSAGES as t, BlockSuggestionPayload as tt, View as u, PayloadIdentity as ut, Mrkdwn as v, buildBlockActionsPayload as vt, SlackAttachmentField as w, Blocks as wt, MessageApp as x, buildViewSubmissionPayload as xt, MrkdwnProps as y, buildBlockSuggestionPayload as yt, MessageUpdate as z };
|
|
943
|
+
//# sourceMappingURL=index-D139DZfD.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
|
|
2
|
-
import { $ as
|
|
3
|
-
export { type ActionContext, type AnyView, Block, type BlockAction, type BlockActionsPayload, type BlockKitContextValue, BlockKitProvider, type BlockKitProviderProps, type BlockProps, type BlockSuggestionPayload, Blocks, type BuildBlockActionsPayloadOptions, type BuildBlockSuggestionPayloadOptions, type BuildViewClosedPayloadOptions, type BuildViewSubmissionPayloadOptions, type Container, Element, type ElementProps, type ElementState, type EmojiOptions, HomeTab, type HomeTabProps, type HomeTabView, type Json, Message, type MessageApi, type MessageApp, type MessageBlockActionsPayload, type MessageContainer, type MessageProps, type MessageUpdate, Modal, type ModalProps, type ModalView, Mrkdwn, type MrkdwnProps, type OptionsResponse, type PayloadContext, type PayloadIdentity, type PayloadTeam, type PayloadUser, type Resolvers, type SlackAttachment, type SlackAttachmentField, type SlackMessageLike, type SlackReaction, type StackedView, type StateValues, type SubmitResult, type SuggestionOption, type Surface, SurfaceScope, type SurfaceScopeProps, type SurfaceScopeValue, Text, type TextObject, Tooltip, type TooltipProps, UserMention, type UserMentionProps, type UserProfile, VALIDATION_MESSAGES, View, type ViewBlockActionsPayload, type ViewContainer, type ViewLike, type ViewProps, type ViewResponseAction, type ViewsApi, blockComponents, buildBlockActionsPayload, buildBlockSuggestionPayload, buildViewClosedPayload, buildViewSubmissionPayload, elementComponents, useBlockKit, useContainer, useLiveView, validateView };
|
|
2
|
+
import { $ as useLiveView, A as BlockAction, B as PayloadContext, C as SlackAttachment, Ct as Block, D as elementComponents, Dt as Json, E as SlackReaction, Et as ElementProps, F as EmojiOptions, G as Surface, H as StackedView, I as LinkProps, J as SurfaceScopeValue, K as SurfaceScope, L as MentionRef, M as BlockKitProvider, N as BlockKitProviderProps, O as Element, P as ElementState, Q as useContainer, R as MessageApi, S as MessageProps, St as blockComponents, T as SlackMessageLike, Tt as BlockProps, U as StateValues, V as Resolvers, W as SubmitResult, X as ViewsApi, Y as UserProfile, Z as useBlockKit, _ as HomeTabView, _t as ViewResponseAction, a as Tooltip, at as BuildViewSubmissionPayloadOptions, b as Message, bt as buildViewClosedPayload, c as TextObject, ct as MessageContainer, d as ViewProps, dt as PayloadTeam, et as BlockActionsPayload, f as Modal, ft as PayloadUser, g as HomeTabProps, gt as ViewLike, h as HomeTab, ht as ViewContainer, i as UserMentionProps, it as BuildViewClosedPayloadOptions, j as BlockKitContextValue, k as ActionContext, l as AnyView, lt as OptionsResponse, m as ModalView, mt as ViewBlockActionsPayload, n as validateView, nt as BuildBlockActionsPayloadOptions, o as TooltipProps, ot as Container, p as ModalProps, pt as SuggestionOption, q as SurfaceScopeProps, r as UserMention, rt as BuildBlockSuggestionPayloadOptions, s as Text, st as MessageBlockActionsPayload, t as VALIDATION_MESSAGES, tt as BlockSuggestionPayload, u as View, ut as PayloadIdentity, v as Mrkdwn, vt as buildBlockActionsPayload, w as SlackAttachmentField, wt as Blocks, x as MessageApp, xt as buildViewSubmissionPayload, y as MrkdwnProps, yt as buildBlockSuggestionPayload, z as MessageUpdate } from "./index-D139DZfD.js";
|
|
3
|
+
export { type ActionContext, type AnyView, Block, type BlockAction, type BlockActionsPayload, type BlockKitContextValue, BlockKitProvider, type BlockKitProviderProps, type BlockProps, type BlockSuggestionPayload, Blocks, type BuildBlockActionsPayloadOptions, type BuildBlockSuggestionPayloadOptions, type BuildViewClosedPayloadOptions, type BuildViewSubmissionPayloadOptions, type Container, Element, type ElementProps, type ElementState, type EmojiOptions, HomeTab, type HomeTabProps, type HomeTabView, type Json, type LinkProps, type MentionRef, Message, type MessageApi, type MessageApp, type MessageBlockActionsPayload, type MessageContainer, type MessageProps, type MessageUpdate, Modal, type ModalProps, type ModalView, Mrkdwn, type MrkdwnProps, type OptionsResponse, type PayloadContext, type PayloadIdentity, type PayloadTeam, type PayloadUser, type Resolvers, type SlackAttachment, type SlackAttachmentField, type SlackMessageLike, type SlackReaction, type StackedView, type StateValues, type SubmitResult, type SuggestionOption, type Surface, SurfaceScope, type SurfaceScopeProps, type SurfaceScopeValue, Text, type TextObject, Tooltip, type TooltipProps, UserMention, type UserMentionProps, type UserProfile, VALIDATION_MESSAGES, View, type ViewBlockActionsPayload, type ViewContainer, type ViewLike, type ViewProps, type ViewResponseAction, type ViewsApi, blockComponents, buildBlockActionsPayload, buildBlockSuggestionPayload, buildViewClosedPayload, buildViewSubmissionPayload, elementComponents, useBlockKit, useContainer, useLiveView, validateView };
|
package/dist/index.js
CHANGED
|
@@ -865,7 +865,7 @@ function newHash() {
|
|
|
865
865
|
return `${Math.floor(Date.now() / 1e3)}.${Math.random().toString(36).slice(2, 10)}`;
|
|
866
866
|
}
|
|
867
867
|
function BlockKitProvider(props) {
|
|
868
|
-
const { children, surface = "message", onAction, onPayload, onSubmit, onClose, onOptions, onStateChange, resolvers, emoji, errors, timeZone, identity, theme } = props;
|
|
868
|
+
const { children, surface = "message", onAction, onPayload, onSubmit, onClose, onOptions, onStateChange, resolvers, linkComponent, mentionHref, emoji, errors, timeZone, identity, theme } = props;
|
|
869
869
|
const [state, setState] = useState({});
|
|
870
870
|
const stateRef = useRef(state);
|
|
871
871
|
const containerRef = useRef(void 0);
|
|
@@ -1041,6 +1041,8 @@ function BlockKitProvider(props) {
|
|
|
1041
1041
|
onSubmit,
|
|
1042
1042
|
onClose,
|
|
1043
1043
|
resolvers: resolvers ?? {},
|
|
1044
|
+
linkComponent,
|
|
1045
|
+
mentionHref,
|
|
1044
1046
|
emoji: emoji ?? {},
|
|
1045
1047
|
errors: stackedView?.errors ?? errors ?? {},
|
|
1046
1048
|
timeZone,
|
|
@@ -1061,6 +1063,8 @@ function BlockKitProvider(props) {
|
|
|
1061
1063
|
onSubmit,
|
|
1062
1064
|
onClose,
|
|
1063
1065
|
resolvers,
|
|
1066
|
+
linkComponent,
|
|
1067
|
+
mentionHref,
|
|
1064
1068
|
emoji,
|
|
1065
1069
|
errors,
|
|
1066
1070
|
timeZone,
|
|
@@ -1228,6 +1232,13 @@ function actionTs(now = Date.now()) {
|
|
|
1228
1232
|
return (now / 1e3).toFixed(6);
|
|
1229
1233
|
}
|
|
1230
1234
|
//#endregion
|
|
1235
|
+
//#region src/useClientLayoutEffect.ts
|
|
1236
|
+
/**
|
|
1237
|
+
* `useLayoutEffect` in the browser and `useEffect` on the server, where neither runs. React 18
|
|
1238
|
+
* warns about every `useLayoutEffect` it meets while server rendering; React 19 doesn't.
|
|
1239
|
+
*/
|
|
1240
|
+
const useClientLayoutEffect = typeof document === "undefined" ? useEffect : useLayoutEffect;
|
|
1241
|
+
//#endregion
|
|
1231
1242
|
//#region src/Tooltip.tsx
|
|
1232
1243
|
/** How long the pointer rests on an anchor before its tooltip shows. */
|
|
1233
1244
|
const SHOW_DELAY_MS = 300;
|
|
@@ -1245,7 +1256,7 @@ function Tooltip({ label, children, placement = "top" }) {
|
|
|
1245
1256
|
const tipRef = useRef(null);
|
|
1246
1257
|
const timer = useRef(void 0);
|
|
1247
1258
|
useEffect(() => () => clearTimeout(timer.current), []);
|
|
1248
|
-
|
|
1259
|
+
useClientLayoutEffect(() => {
|
|
1249
1260
|
if (!open) {
|
|
1250
1261
|
setPosition(null);
|
|
1251
1262
|
return;
|
|
@@ -5599,6 +5610,44 @@ function Emoji({ name, skinTone, size = 22 }) {
|
|
|
5599
5610
|
});
|
|
5600
5611
|
}
|
|
5601
5612
|
//#endregion
|
|
5613
|
+
//#region src/Link.tsx
|
|
5614
|
+
/**
|
|
5615
|
+
* A link from the payload, rendered by the provider's `linkComponent` when it has one. Without an
|
|
5616
|
+
* `href` (a payload missing its URL) it stays a plain `<a>`, so the app's component always gets one.
|
|
5617
|
+
*/
|
|
5618
|
+
function Link({ href, children, ...props }) {
|
|
5619
|
+
const { linkComponent: Component } = useBlockKit();
|
|
5620
|
+
if (Component && href !== void 0) return /* @__PURE__ */ jsx(Component, {
|
|
5621
|
+
href,
|
|
5622
|
+
...props,
|
|
5623
|
+
children
|
|
5624
|
+
});
|
|
5625
|
+
return /* @__PURE__ */ jsx("a", {
|
|
5626
|
+
href,
|
|
5627
|
+
...props,
|
|
5628
|
+
children
|
|
5629
|
+
});
|
|
5630
|
+
}
|
|
5631
|
+
/**
|
|
5632
|
+
* A resolved channel or user group mention: a link to the app's page for it when `mentionHref`
|
|
5633
|
+
* returns one, otherwise the plain pill. Both keep the pill's class, so they look the same.
|
|
5634
|
+
*/
|
|
5635
|
+
function MentionLink({ type, id, children }) {
|
|
5636
|
+
const { mentionHref } = useBlockKit();
|
|
5637
|
+
const href = mentionHref?.({
|
|
5638
|
+
type,
|
|
5639
|
+
id
|
|
5640
|
+
});
|
|
5641
|
+
return href === void 0 ? /* @__PURE__ */ jsx("span", {
|
|
5642
|
+
className: "sbk-mention",
|
|
5643
|
+
children
|
|
5644
|
+
}) : /* @__PURE__ */ jsx(Link, {
|
|
5645
|
+
className: "sbk-mention",
|
|
5646
|
+
href,
|
|
5647
|
+
children
|
|
5648
|
+
});
|
|
5649
|
+
}
|
|
5650
|
+
//#endregion
|
|
5602
5651
|
//#region src/UserMention.tsx
|
|
5603
5652
|
function localTime(timeZone) {
|
|
5604
5653
|
try {
|
|
@@ -5617,13 +5666,13 @@ function localTime(timeZone) {
|
|
|
5617
5666
|
* `resolvers.userProfile` and falling back to the display name alone.
|
|
5618
5667
|
*/
|
|
5619
5668
|
function UserMention({ id, name }) {
|
|
5620
|
-
const { resolvers, theme } = useBlockKit();
|
|
5669
|
+
const { resolvers, theme, mentionHref } = useBlockKit();
|
|
5621
5670
|
const [open, setOpen] = useState(false);
|
|
5622
5671
|
const [position, setPosition] = useState(null);
|
|
5623
5672
|
const anchorRef = useRef(null);
|
|
5624
5673
|
const cardRef = useRef(null);
|
|
5625
5674
|
const cardId = useId();
|
|
5626
|
-
|
|
5675
|
+
useClientLayoutEffect(() => {
|
|
5627
5676
|
if (!open) {
|
|
5628
5677
|
setPosition(null);
|
|
5629
5678
|
return;
|
|
@@ -5668,6 +5717,10 @@ function UserMention({ id, name }) {
|
|
|
5668
5717
|
}
|
|
5669
5718
|
const profile = open ? resolvers.userProfile?.(id) ?? { name } : void 0;
|
|
5670
5719
|
const time = profile?.timeZone ? localTime(profile.timeZone) : void 0;
|
|
5720
|
+
const href = profile ? mentionHref?.({
|
|
5721
|
+
type: "user",
|
|
5722
|
+
id
|
|
5723
|
+
}) : void 0;
|
|
5671
5724
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
|
|
5672
5725
|
ref: anchorRef,
|
|
5673
5726
|
className: "sbk-mention sbk-mention--user",
|
|
@@ -5707,7 +5760,11 @@ function UserMention({ id, name }) {
|
|
|
5707
5760
|
children: [
|
|
5708
5761
|
/* @__PURE__ */ jsxs("div", {
|
|
5709
5762
|
className: "sbk-profile-card__name",
|
|
5710
|
-
children: [profile.name
|
|
5763
|
+
children: [href === void 0 ? profile.name : /* @__PURE__ */ jsx(Link, {
|
|
5764
|
+
className: "sbk-profile-card__name-link",
|
|
5765
|
+
href,
|
|
5766
|
+
children: profile.name
|
|
5767
|
+
}), profile.pronouns && /* @__PURE__ */ jsx("span", {
|
|
5711
5768
|
className: "sbk-profile-card__pronouns",
|
|
5712
5769
|
children: profile.pronouns
|
|
5713
5770
|
})]
|
|
@@ -5767,7 +5824,7 @@ function renderNode(node, resolvers, timeZone, emojiSize) {
|
|
|
5767
5824
|
className: "sbk-mrkdwn__quote",
|
|
5768
5825
|
children: renderNodes(node.children, resolvers, timeZone, emojiSize)
|
|
5769
5826
|
});
|
|
5770
|
-
case "link": return /* @__PURE__ */ jsx(
|
|
5827
|
+
case "link": return /* @__PURE__ */ jsx(Link, {
|
|
5771
5828
|
className: "sbk-link",
|
|
5772
5829
|
href: node.url,
|
|
5773
5830
|
target: "_blank",
|
|
@@ -5783,8 +5840,9 @@ function renderNode(node, resolvers, timeZone, emojiSize) {
|
|
|
5783
5840
|
}
|
|
5784
5841
|
case "usergroup": {
|
|
5785
5842
|
const name = resolvers.usergroup?.(node.id);
|
|
5786
|
-
return name ? /* @__PURE__ */ jsxs(
|
|
5787
|
-
|
|
5843
|
+
return name ? /* @__PURE__ */ jsxs(MentionLink, {
|
|
5844
|
+
type: "usergroup",
|
|
5845
|
+
id: node.id,
|
|
5788
5846
|
children: ["@", name]
|
|
5789
5847
|
}) : /* @__PURE__ */ jsx("span", {
|
|
5790
5848
|
className: "sbk-mention--loading",
|
|
@@ -5793,8 +5851,9 @@ function renderNode(node, resolvers, timeZone, emojiSize) {
|
|
|
5793
5851
|
}
|
|
5794
5852
|
case "channel": {
|
|
5795
5853
|
const name = resolvers.channel?.(node.id) ?? node.label;
|
|
5796
|
-
return name ? /* @__PURE__ */ jsxs(
|
|
5797
|
-
|
|
5854
|
+
return name ? /* @__PURE__ */ jsxs(MentionLink, {
|
|
5855
|
+
type: "channel",
|
|
5856
|
+
id: node.id,
|
|
5798
5857
|
children: ["#", name]
|
|
5799
5858
|
}) : /* @__PURE__ */ jsxs("span", {
|
|
5800
5859
|
className: "sbk-mention--private",
|
|
@@ -5807,7 +5866,7 @@ function renderNode(node, resolvers, timeZone, emojiSize) {
|
|
|
5807
5866
|
});
|
|
5808
5867
|
case "date": {
|
|
5809
5868
|
const text = formatSlackDate(node.timestamp, node.format, { timeZone });
|
|
5810
|
-
return node.url ? /* @__PURE__ */ jsx(
|
|
5869
|
+
return node.url ? /* @__PURE__ */ jsx(Link, {
|
|
5811
5870
|
className: "sbk-link",
|
|
5812
5871
|
href: node.url,
|
|
5813
5872
|
target: "_blank",
|
|
@@ -5979,7 +6038,9 @@ function Button({ element, blockId }) {
|
|
|
5979
6038
|
* Slack's `focus_on_load`: the element takes focus when its modal or Home tab opens. Slack ignores
|
|
5980
6039
|
* it in messages and allows it on only one element per view.
|
|
5981
6040
|
*
|
|
5982
|
-
* Pass the element's own ref when it already has one; otherwise attach the returned ref.
|
|
6041
|
+
* Pass the element's own ref when it already has one; otherwise attach the returned ref. The return
|
|
6042
|
+
* type is `useRef`'s own, which differs between @types/react 18 and 19, so it fits a `ref` prop in
|
|
6043
|
+
* both.
|
|
5983
6044
|
*/
|
|
5984
6045
|
function useFocusOnLoad(element, existing) {
|
|
5985
6046
|
const { surface } = useBlockKit();
|
|
@@ -6247,10 +6308,10 @@ function Popover({ anchorRef, onDismiss, gap = DEFAULT_GAP, children }) {
|
|
|
6247
6308
|
const layerRef = useRef(null);
|
|
6248
6309
|
const [position, setPosition] = useState(null);
|
|
6249
6310
|
const dismiss = useRef(onDismiss);
|
|
6250
|
-
|
|
6311
|
+
useClientLayoutEffect(() => {
|
|
6251
6312
|
dismiss.current = onDismiss;
|
|
6252
6313
|
});
|
|
6253
|
-
|
|
6314
|
+
useClientLayoutEffect(() => {
|
|
6254
6315
|
function place() {
|
|
6255
6316
|
const anchor = anchorRef.current;
|
|
6256
6317
|
const layer = layerRef.current;
|
|
@@ -8179,7 +8240,8 @@ function Collapse({ open, className, children }) {
|
|
|
8179
8240
|
const [shown, setShown] = useState(open);
|
|
8180
8241
|
if (open && !shown) setShown(true);
|
|
8181
8242
|
const was = useRef(open);
|
|
8182
|
-
|
|
8243
|
+
useClientLayoutEffect(() => {
|
|
8244
|
+
ref.current?.toggleAttribute("inert", !open);
|
|
8183
8245
|
if (was.current === open) return;
|
|
8184
8246
|
was.current = open;
|
|
8185
8247
|
const el = ref.current;
|
|
@@ -8197,7 +8259,6 @@ function Collapse({ open, className, children }) {
|
|
|
8197
8259
|
return /* @__PURE__ */ jsx("div", {
|
|
8198
8260
|
ref,
|
|
8199
8261
|
className: className ? `sbk-collapse ${className}` : "sbk-collapse",
|
|
8200
|
-
inert: !open,
|
|
8201
8262
|
onTransitionEnd: (e) => {
|
|
8202
8263
|
if (e.target !== e.currentTarget || e.propertyName !== "height") return;
|
|
8203
8264
|
if (open) e.currentTarget.style.height = "";
|
|
@@ -8355,7 +8416,7 @@ function RichTextMiniSection({ section }) {
|
|
|
8355
8416
|
function RichTextMiniLeaf({ element }) {
|
|
8356
8417
|
if (element.type === "link") {
|
|
8357
8418
|
const text = typeof element.text === "string" ? element.text : String(element.url ?? "");
|
|
8358
|
-
return /* @__PURE__ */ jsx(
|
|
8419
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
8359
8420
|
className: "sbk-rtmini__link",
|
|
8360
8421
|
href: typeof element.url === "string" ? element.url : void 0,
|
|
8361
8422
|
target: "_blank",
|
|
@@ -8390,7 +8451,7 @@ function DataTableCell({ cell }) {
|
|
|
8390
8451
|
if (!cell || typeof cell !== "object") return null;
|
|
8391
8452
|
switch (cell.type) {
|
|
8392
8453
|
case "rich_text": return /* @__PURE__ */ jsx(RichTextMini, { value: cell });
|
|
8393
|
-
case "url": return /* @__PURE__ */ jsx(
|
|
8454
|
+
case "url": return /* @__PURE__ */ jsx(Link, {
|
|
8394
8455
|
className: "sbk-rtmini__link",
|
|
8395
8456
|
href: typeof cell.url === "string" ? cell.url : void 0,
|
|
8396
8457
|
target: "_blank",
|
|
@@ -9703,7 +9764,7 @@ function renderInlineNode(node) {
|
|
|
9703
9764
|
});
|
|
9704
9765
|
case "link": {
|
|
9705
9766
|
const link = node;
|
|
9706
|
-
return /* @__PURE__ */ jsx(
|
|
9767
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
9707
9768
|
className: "sbk-link",
|
|
9708
9769
|
href: link.url,
|
|
9709
9770
|
target: "_blank",
|
|
@@ -9886,7 +9947,7 @@ function TaskRow({ task }) {
|
|
|
9886
9947
|
}) : null,
|
|
9887
9948
|
sources.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
9888
9949
|
className: "sbk-plan__task-sources",
|
|
9889
|
-
children: sources.map((source, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
9950
|
+
children: sources.map((source, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, {
|
|
9890
9951
|
className: "sbk-plan__task-source-link",
|
|
9891
9952
|
href: source.url,
|
|
9892
9953
|
target: "_blank",
|
|
@@ -10023,7 +10084,7 @@ function renderLeaf(el, ctx, emojiSize, isFirst = false) {
|
|
|
10023
10084
|
content = renderTextWithBreaks(el.text, isFirst);
|
|
10024
10085
|
break;
|
|
10025
10086
|
case "link":
|
|
10026
|
-
content = /* @__PURE__ */ jsx(
|
|
10087
|
+
content = /* @__PURE__ */ jsx(Link, {
|
|
10027
10088
|
className: "sbk-link",
|
|
10028
10089
|
href: el.url,
|
|
10029
10090
|
target: "_blank",
|
|
@@ -10053,8 +10114,9 @@ function renderLeaf(el, ctx, emojiSize, isFirst = false) {
|
|
|
10053
10114
|
}
|
|
10054
10115
|
case "usergroup": {
|
|
10055
10116
|
const name = ctx.resolvers.usergroup?.(el.usergroup_id);
|
|
10056
|
-
content = name ? /* @__PURE__ */ jsxs(
|
|
10057
|
-
|
|
10117
|
+
content = name ? /* @__PURE__ */ jsxs(MentionLink, {
|
|
10118
|
+
type: "usergroup",
|
|
10119
|
+
id: el.usergroup_id,
|
|
10058
10120
|
children: ["@", name]
|
|
10059
10121
|
}) : /* @__PURE__ */ jsx("span", {
|
|
10060
10122
|
className: "sbk-mention--loading",
|
|
@@ -10064,8 +10126,9 @@ function renderLeaf(el, ctx, emojiSize, isFirst = false) {
|
|
|
10064
10126
|
}
|
|
10065
10127
|
case "channel": {
|
|
10066
10128
|
const name = ctx.resolvers.channel?.(el.channel_id);
|
|
10067
|
-
content = name ? /* @__PURE__ */ jsxs(
|
|
10068
|
-
|
|
10129
|
+
content = name ? /* @__PURE__ */ jsxs(MentionLink, {
|
|
10130
|
+
type: "channel",
|
|
10131
|
+
id: el.channel_id,
|
|
10069
10132
|
children: ["#", name]
|
|
10070
10133
|
}) : /* @__PURE__ */ jsxs("span", {
|
|
10071
10134
|
className: "sbk-mention--private",
|
|
@@ -10081,7 +10144,7 @@ function renderLeaf(el, ctx, emojiSize, isFirst = false) {
|
|
|
10081
10144
|
break;
|
|
10082
10145
|
case "date": {
|
|
10083
10146
|
const text = formatSlackDate(el.timestamp, el.format, { timeZone: ctx.timeZone });
|
|
10084
|
-
content = el.url ? /* @__PURE__ */ jsx(
|
|
10147
|
+
content = el.url ? /* @__PURE__ */ jsx(Link, {
|
|
10085
10148
|
className: "sbk-link",
|
|
10086
10149
|
href: el.url,
|
|
10087
10150
|
target: "_blank",
|
|
@@ -10155,7 +10218,7 @@ function renderTextWithBreaks(value, isFirst) {
|
|
|
10155
10218
|
*/
|
|
10156
10219
|
function renderPreformattedLines(elements) {
|
|
10157
10220
|
return elements.map((el, i) => {
|
|
10158
|
-
if (el.type === "link") return /* @__PURE__ */ jsx(Fragment$1, { children: applyStyle(/* @__PURE__ */ jsx(
|
|
10221
|
+
if (el.type === "link") return /* @__PURE__ */ jsx(Fragment$1, { children: applyStyle(/* @__PURE__ */ jsx(Link, {
|
|
10159
10222
|
className: "sbk-link",
|
|
10160
10223
|
href: el.url,
|
|
10161
10224
|
target: "_blank",
|
|
@@ -10381,7 +10444,7 @@ function TaskCard({ block }) {
|
|
|
10381
10444
|
children: /* @__PURE__ */ jsx(RichTextMini, { value: block.output })
|
|
10382
10445
|
}) : null, sources.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
10383
10446
|
className: "sbk-task-card__sources",
|
|
10384
|
-
children: sources.map((source, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
10447
|
+
children: sources.map((source, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, {
|
|
10385
10448
|
className: "sbk-task-card__source-link",
|
|
10386
10449
|
href: source.url,
|
|
10387
10450
|
target: "_blank",
|
|
@@ -10467,7 +10530,7 @@ function Video({ block }) {
|
|
|
10467
10530
|
}),
|
|
10468
10531
|
title && /* @__PURE__ */ jsxs("div", {
|
|
10469
10532
|
className: "sbk-video__title",
|
|
10470
|
-
children: [titleUrl ? /* @__PURE__ */ jsx(
|
|
10533
|
+
children: [titleUrl ? /* @__PURE__ */ jsx(Link, {
|
|
10471
10534
|
href: titleUrl,
|
|
10472
10535
|
target: "_blank",
|
|
10473
10536
|
rel: "noreferrer",
|
|
@@ -10478,7 +10541,7 @@ function Video({ block }) {
|
|
|
10478
10541
|
children: /* @__PURE__ */ jsx(CaretDownIcon, {})
|
|
10479
10542
|
})]
|
|
10480
10543
|
}),
|
|
10481
|
-
/* @__PURE__ */ jsxs(
|
|
10544
|
+
/* @__PURE__ */ jsxs(Link, {
|
|
10482
10545
|
className: "sbk-video__frame",
|
|
10483
10546
|
href: typeof json.video_url === "string" ? json.video_url : titleUrl,
|
|
10484
10547
|
target: "_blank",
|
|
@@ -10745,7 +10808,7 @@ function Attachment({ attachment }) {
|
|
|
10745
10808
|
className: "sbk-attachment__author-icon",
|
|
10746
10809
|
src: attachment.author_icon,
|
|
10747
10810
|
alt: ""
|
|
10748
|
-
}), attachment.author_link ? /* @__PURE__ */ jsx(
|
|
10811
|
+
}), attachment.author_link ? /* @__PURE__ */ jsx(Link, {
|
|
10749
10812
|
className: "sbk-link",
|
|
10750
10813
|
href: attachment.author_link,
|
|
10751
10814
|
target: "_blank",
|
|
@@ -10755,7 +10818,7 @@ function Attachment({ attachment }) {
|
|
|
10755
10818
|
}),
|
|
10756
10819
|
attachment.title && /* @__PURE__ */ jsx("div", {
|
|
10757
10820
|
className: "sbk-attachment__title",
|
|
10758
|
-
children: attachment.title_link ? /* @__PURE__ */ jsx(
|
|
10821
|
+
children: attachment.title_link ? /* @__PURE__ */ jsx(Link, {
|
|
10759
10822
|
className: "sbk-link",
|
|
10760
10823
|
href: attachment.title_link,
|
|
10761
10824
|
target: "_blank",
|