@shipfox/client-integrations 14.0.0 → 16.0.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +35 -0
- package/dist/application/complete-integration-callback.d.ts +2 -2
- package/dist/components/callback-status-shell.js +3 -3
- package/dist/components/callback-status-shell.js.map +1 -1
- package/dist/components/connection-picker.js +3 -3
- package/dist/components/connection-picker.js.map +1 -1
- package/dist/components/installed-integrations-section.js +9 -9
- package/dist/components/installed-integrations-section.js.map +1 -1
- package/dist/components/integration-delete-confirm-modal.js +1 -1
- package/dist/components/integration-delete-confirm-modal.js.map +1 -1
- package/dist/components/integration-gallery-for-workspace.js +3 -3
- package/dist/components/integration-gallery-for-workspace.js.map +1 -1
- package/dist/components/integration-gallery.stories.d.ts +1 -0
- package/dist/components/integration-gallery.stories.d.ts.map +1 -1
- package/dist/components/integration-gallery.stories.js +28 -0
- package/dist/components/integration-gallery.stories.js.map +1 -1
- package/dist/components/integration-usage-modal.d.ts +1 -1
- package/dist/components/integration-usage-modal.d.ts.map +1 -1
- package/dist/components/integration-usage-modal.js +8 -7
- package/dist/components/integration-usage-modal.js.map +1 -1
- package/dist/components/provider-grid.d.ts +1 -1
- package/dist/components/provider-grid.d.ts.map +1 -1
- package/dist/components/provider-grid.js +10 -10
- package/dist/components/provider-grid.js.map +1 -1
- package/dist/components/redirect-install-page.js +1 -1
- package/dist/components/redirect-install-page.js.map +1 -1
- package/dist/components/repository-picker.js +4 -4
- package/dist/components/repository-picker.js.map +1 -1
- package/dist/components/webhook/copyable-value.js +3 -3
- package/dist/components/webhook/copyable-value.js.map +1 -1
- package/dist/components/webhook/webhook-create-modal.js +1 -1
- package/dist/components/webhook/webhook-create-modal.js.map +1 -1
- package/dist/components/webhook/webhook-modals.stories.d.ts.map +1 -1
- package/dist/components/webhook/webhook-usage-details.js +2 -2
- package/dist/components/webhook/webhook-usage-details.js.map +1 -1
- package/dist/feature.d.ts +8 -8
- package/dist/feature.d.ts.map +1 -1
- package/dist/hooks/api/integrations.d.ts +4 -4
- package/dist/hooks/api/integrations.d.ts.map +1 -1
- package/dist/hooks/api/webhook-connections.d.ts +1 -1
- package/dist/hooks/api/webhook-connections.d.ts.map +1 -1
- package/dist/pages/gitea-install-page.js +4 -4
- package/dist/pages/gitea-install-page.js.map +1 -1
- package/dist/pages/jira-callback-page.js +7 -7
- package/dist/pages/jira-callback-page.js.map +1 -1
- package/dist/pages/sentry-callback-page.js +7 -7
- package/dist/pages/sentry-callback-page.js.map +1 -1
- package/dist/pages/source-control-onboarding-page.js +2 -2
- package/dist/pages/source-control-onboarding-page.js.map +1 -1
- package/dist/routes/gitea.d.ts.map +1 -1
- package/dist/routes/github-callback.d.ts.map +1 -1
- package/dist/routes/github.d.ts.map +1 -1
- package/dist/routes/integrations-settings.d.ts.map +1 -1
- package/dist/routes/integrations.d.ts.map +1 -1
- package/dist/routes/jira-callback.d.ts.map +1 -1
- package/dist/routes/jira.d.ts.map +1 -1
- package/dist/routes/linear-callback.d.ts.map +1 -1
- package/dist/routes/linear.d.ts.map +1 -1
- package/dist/routes/sentry-callback.d.ts.map +1 -1
- package/dist/routes/sentry.d.ts.map +1 -1
- package/dist/routes/slack-callback.d.ts.map +1 -1
- package/dist/routes/slack.d.ts.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/src/components/callback-status-shell.tsx +3 -3
- package/src/components/connection-picker.tsx +3 -3
- package/src/components/installed-integrations-section.tsx +9 -9
- package/src/components/integration-delete-confirm-modal.tsx +1 -1
- package/src/components/integration-gallery-for-workspace.tsx +3 -3
- package/src/components/integration-gallery.stories.tsx +20 -0
- package/src/components/integration-gallery.test.tsx +21 -0
- package/src/components/integration-usage-modal.tsx +9 -7
- package/src/components/provider-grid.tsx +10 -10
- package/src/components/redirect-install-page.tsx +1 -1
- package/src/components/repository-picker.test.tsx +2 -2
- package/src/components/repository-picker.tsx +6 -4
- package/src/components/webhook/copyable-value.tsx +3 -3
- package/src/components/webhook/webhook-create-modal.tsx +1 -1
- package/src/components/webhook/webhook-usage-details.tsx +2 -2
- package/src/pages/gitea-install-page.tsx +4 -4
- package/src/pages/jira-callback-page.tsx +7 -7
- package/src/pages/sentry-callback-page.tsx +7 -7
- package/src/pages/source-control-onboarding-page.tsx +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-usage-modal.d.ts","sourceRoot":"","sources":["../../src/components/integration-usage-modal.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGrC,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,0BAA0B;IAClC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAID,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,QAAQ,GACT,EAAE,0BAA0B
|
|
1
|
+
{"version":3,"file":"integration-usage-modal.d.ts","sourceRoot":"","sources":["../../src/components/integration-usage-modal.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAGrC,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,0BAA0B;IAClC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzC,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAID,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,QAAQ,GACT,EAAE,0BAA0B,sCAiH5B"}
|
|
@@ -30,8 +30,9 @@ export function IntegrationUsageModal({ connection, events, open, onOpenChange,
|
|
|
30
30
|
workflowExample
|
|
31
31
|
]);
|
|
32
32
|
const title = connection ? `Use ${connection.displayName}` : 'Use integration';
|
|
33
|
+
if (!open || connection === null) return null;
|
|
33
34
|
return /*#__PURE__*/ _jsx(Modal, {
|
|
34
|
-
open: open
|
|
35
|
+
open: open,
|
|
35
36
|
onOpenChange: onOpenChange,
|
|
36
37
|
children: /*#__PURE__*/ _jsxs(ModalContent, {
|
|
37
38
|
"aria-describedby": undefined,
|
|
@@ -43,10 +44,10 @@ export function IntegrationUsageModal({ connection, events, open, onOpenChange,
|
|
|
43
44
|
}),
|
|
44
45
|
/*#__PURE__*/ _jsx(ModalHeader, {
|
|
45
46
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
46
|
-
className: "flex min-w-0 flex-col gap-
|
|
47
|
+
className: "flex min-w-0 flex-col gap-tight",
|
|
47
48
|
children: [
|
|
48
49
|
/*#__PURE__*/ _jsxs("div", {
|
|
49
|
-
className: "flex min-w-0 items-center gap-
|
|
50
|
+
className: "flex min-w-0 items-center gap-inline",
|
|
50
51
|
children: [
|
|
51
52
|
/*#__PURE__*/ _jsx(Text, {
|
|
52
53
|
size: "lg",
|
|
@@ -71,10 +72,10 @@ export function IntegrationUsageModal({ connection, events, open, onOpenChange,
|
|
|
71
72
|
connection ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
72
73
|
children: [
|
|
73
74
|
/*#__PURE__*/ _jsxs(ModalBody, {
|
|
74
|
-
className: "min-h-0 flex-1 gap-
|
|
75
|
+
className: "min-h-0 flex-1 gap-section overflow-y-auto overflow-x-clip scrollbar",
|
|
75
76
|
children: [
|
|
76
77
|
/*#__PURE__*/ _jsxs("section", {
|
|
77
|
-
className: "flex w-full flex-col gap-
|
|
78
|
+
className: "flex w-full flex-col gap-cluster",
|
|
78
79
|
children: [
|
|
79
80
|
/*#__PURE__*/ _jsx(Text, {
|
|
80
81
|
size: "md",
|
|
@@ -82,7 +83,7 @@ export function IntegrationUsageModal({ connection, events, open, onOpenChange,
|
|
|
82
83
|
children: "Usage"
|
|
83
84
|
}),
|
|
84
85
|
events.length > 1 ? /*#__PURE__*/ _jsxs("div", {
|
|
85
|
-
className: "flex flex-col gap-
|
|
86
|
+
className: "flex flex-col gap-inline",
|
|
86
87
|
children: [
|
|
87
88
|
/*#__PURE__*/ _jsx("label", {
|
|
88
89
|
htmlFor: "integration-usage-event",
|
|
@@ -143,7 +144,7 @@ export function IntegrationUsageModal({ connection, events, open, onOpenChange,
|
|
|
143
144
|
]
|
|
144
145
|
}),
|
|
145
146
|
children ? /*#__PURE__*/ _jsxs("section", {
|
|
146
|
-
className: "flex w-full flex-col gap-
|
|
147
|
+
className: "flex w-full flex-col gap-cluster",
|
|
147
148
|
children: [
|
|
148
149
|
/*#__PURE__*/ _jsx(Text, {
|
|
149
150
|
size: "md",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/integration-usage-modal.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {\n CodeBlock,\n CodeBlockBody,\n CodeBlockContent,\n CodeBlockCopyButton,\n CodeBlockFilename,\n CodeBlockFiles,\n CodeBlockHeader,\n CodeBlockItem,\n} from '@shipfox/react-ui/code-block';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '@shipfox/react-ui/modal';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@shipfox/react-ui/select';\nimport {Text} from '@shipfox/react-ui/typography';\nimport type {ReactNode} from 'react';\nimport {useEffect, useMemo, useState} from 'react';\nimport {ConnectionStatusBadge} from '#connection-status-badge.js';\nimport type {IntegrationConnection} from '#core/models.js';\n\nexport interface IntegrationUsageEvent {\n value: string;\n label: string;\n}\n\ninterface IntegrationUsageModalProps {\n connection: IntegrationConnection | null;\n events: IntegrationUsageEvent[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n children?: ReactNode;\n}\n\nconst WORKFLOW_FILENAME = '.shipfox/workflows/integration.yml';\n\nexport function IntegrationUsageModal({\n connection,\n events,\n open,\n onOpenChange,\n children,\n}: IntegrationUsageModalProps) {\n const [selectedEvent, setSelectedEvent] = useState('');\n const eventValuesKey = events.map((event) => event.value).join('\\u0000');\n\n useEffect(() => {\n const eventValues = eventValuesKey ? eventValuesKey.split('\\u0000') : [];\n setSelectedEvent((current) =>\n eventValues.includes(current) ? current : (eventValues[0] ?? ''),\n );\n }, [eventValuesKey]);\n\n const workflowExample = connection\n ? buildWorkflowExample({source: connection.slug, event: selectedEvent})\n : '';\n const data = useMemo(\n () => [{language: 'yaml', filename: WORKFLOW_FILENAME, code: workflowExample}],\n [workflowExample],\n );\n const title = connection ? `Use ${connection.displayName}` : 'Use integration';\n\n return (\n <Modal open={open
|
|
1
|
+
{"version":3,"sources":["../../src/components/integration-usage-modal.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {\n CodeBlock,\n CodeBlockBody,\n CodeBlockContent,\n CodeBlockCopyButton,\n CodeBlockFilename,\n CodeBlockFiles,\n CodeBlockHeader,\n CodeBlockItem,\n} from '@shipfox/react-ui/code-block';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '@shipfox/react-ui/modal';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@shipfox/react-ui/select';\nimport {Text} from '@shipfox/react-ui/typography';\nimport type {ReactNode} from 'react';\nimport {useEffect, useMemo, useState} from 'react';\nimport {ConnectionStatusBadge} from '#connection-status-badge.js';\nimport type {IntegrationConnection} from '#core/models.js';\n\nexport interface IntegrationUsageEvent {\n value: string;\n label: string;\n}\n\ninterface IntegrationUsageModalProps {\n connection: IntegrationConnection | null;\n events: IntegrationUsageEvent[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n children?: ReactNode;\n}\n\nconst WORKFLOW_FILENAME = '.shipfox/workflows/integration.yml';\n\nexport function IntegrationUsageModal({\n connection,\n events,\n open,\n onOpenChange,\n children,\n}: IntegrationUsageModalProps) {\n const [selectedEvent, setSelectedEvent] = useState('');\n const eventValuesKey = events.map((event) => event.value).join('\\u0000');\n\n useEffect(() => {\n const eventValues = eventValuesKey ? eventValuesKey.split('\\u0000') : [];\n setSelectedEvent((current) =>\n eventValues.includes(current) ? current : (eventValues[0] ?? ''),\n );\n }, [eventValuesKey]);\n\n const workflowExample = connection\n ? buildWorkflowExample({source: connection.slug, event: selectedEvent})\n : '';\n const data = useMemo(\n () => [{language: 'yaml', filename: WORKFLOW_FILENAME, code: workflowExample}],\n [workflowExample],\n );\n const title = connection ? `Use ${connection.displayName}` : 'Use integration';\n\n if (!open || connection === null) return null;\n\n return (\n <Modal open={open} onOpenChange={onOpenChange}>\n <ModalContent aria-describedby={undefined} className=\"max-h-[calc(100vh-32px)] max-w-[640px]\">\n <ModalTitle className=\"sr-only\">{title}</ModalTitle>\n <ModalHeader>\n <div className=\"flex min-w-0 flex-col gap-tight\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Text size=\"lg\" aria-hidden=\"true\" className=\"truncate\">\n {title}\n </Text>\n {connection ? (\n <ConnectionStatusBadge status={connection.lifecycleStatus} className=\"shrink-0\" />\n ) : null}\n </div>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Reference this connection from a workflow trigger.\n </Text>\n </div>\n </ModalHeader>\n {connection ? (\n <>\n <ModalBody className=\"min-h-0 flex-1 gap-section overflow-y-auto overflow-x-clip scrollbar\">\n <section className=\"flex w-full flex-col gap-cluster\">\n <Text size=\"md\" bold>\n Usage\n </Text>\n {events.length > 1 ? (\n <div className=\"flex flex-col gap-inline\">\n <label\n htmlFor=\"integration-usage-event\"\n className=\"font-display text-sm font-medium text-foreground-neutral-base\"\n >\n Event\n </label>\n <Select value={selectedEvent} onValueChange={setSelectedEvent}>\n <SelectTrigger id=\"integration-usage-event\">\n <SelectValue placeholder=\"Select event\" />\n </SelectTrigger>\n <SelectContent>\n {events.map((event) => (\n <SelectItem key={event.value} value={event.value}>\n {event.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n <CodeBlock data={data} className=\"h-auto min-h-0 rounded-8\">\n <CodeBlockHeader>\n <CodeBlockFiles>\n {(item) => (\n <CodeBlockFilename value={item.filename}>{item.filename}</CodeBlockFilename>\n )}\n </CodeBlockFiles>\n <CodeBlockCopyButton />\n </CodeBlockHeader>\n <CodeBlockBody>\n {(item) => (\n <CodeBlockItem value={item.filename}>\n <CodeBlockContent\n language=\"yaml\"\n syntaxHighlighting\n highlightedLineRange={{startLine: 3, endLine: 4}}\n >\n {item.code}\n </CodeBlockContent>\n </CodeBlockItem>\n )}\n </CodeBlockBody>\n </CodeBlock>\n </section>\n {children ? (\n <section className=\"flex w-full flex-col gap-cluster\">\n <Text size=\"md\" bold>\n Details\n </Text>\n {children}\n </section>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <Button type=\"button\" onClick={() => onOpenChange(false)}>\n Done\n </Button>\n </ModalFooter>\n </>\n ) : null}\n </ModalContent>\n </Modal>\n );\n}\n\nfunction buildWorkflowExample({source, event}: {source: string; event: string}) {\n return [\n 'triggers:',\n ' integration:',\n ` source: ${source}`,\n ` event: ${event}`,\n 'jobs:',\n ' handle-event:',\n ' steps:',\n ' - run: echo \"Received event\"',\n ].join('\\n');\n}\n"],"names":["Button","CodeBlock","CodeBlockBody","CodeBlockContent","CodeBlockCopyButton","CodeBlockFilename","CodeBlockFiles","CodeBlockHeader","CodeBlockItem","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","Text","useEffect","useMemo","useState","ConnectionStatusBadge","WORKFLOW_FILENAME","IntegrationUsageModal","connection","events","open","onOpenChange","children","selectedEvent","setSelectedEvent","eventValuesKey","map","event","value","join","eventValues","split","current","includes","workflowExample","buildWorkflowExample","source","slug","data","language","filename","code","title","displayName","aria-describedby","undefined","className","div","size","aria-hidden","status","lifecycleStatus","section","bold","length","label","htmlFor","onValueChange","id","placeholder","item","syntaxHighlighting","highlightedLineRange","startLine","endLine","type","onClick"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ export interface ProviderGridProps {
|
|
|
11
11
|
errorSubject?: string;
|
|
12
12
|
onOpenProvider?: ((provider: string) => void) | undefined;
|
|
13
13
|
}
|
|
14
|
-
export declare const PROVIDER_GRID_CLASS = "grid grid-cols-2 gap-
|
|
14
|
+
export declare const PROVIDER_GRID_CLASS = "grid grid-cols-2 gap-cluster max-[760px]:grid-cols-1";
|
|
15
15
|
export declare const PROVIDER_SURFACE_CLASS = "overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base";
|
|
16
16
|
export declare function ProviderGrid({ workspaceSlug, providers, isPending, isFetching, error, onRetry, emptyMessage, loadingLabel, errorSubject, onOpenProvider, }: ProviderGridProps): import("react").JSX.Element;
|
|
17
17
|
//# sourceMappingURL=provider-grid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-grid.d.ts","sourceRoot":"","sources":["../../src/components/provider-grid.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAGzD,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC3D;AAED,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"provider-grid.d.ts","sourceRoot":"","sources":["../../src/components/provider-grid.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAGzD,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CAC3D;AAED,eAAO,MAAM,mBAAmB,yDAAyD,CAAC;AAE1F,eAAO,MAAM,sBAAsB,2FACuD,CAAC;AAE3F,wBAAgB,YAAY,CAAC,EAC3B,aAAa,EACb,SAAS,EACT,SAAS,EACT,UAAkB,EAClB,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAkC,EAClC,YAAuC,EACvC,cAAc,GACf,EAAE,iBAAiB,+BA+CnB"}
|
|
@@ -9,7 +9,7 @@ import { Text } from '@shipfox/react-ui/typography';
|
|
|
9
9
|
import { cn } from '@shipfox/react-ui/utils';
|
|
10
10
|
import { Link } from '@tanstack/react-router';
|
|
11
11
|
import { PROVIDER_CATALOG } from '#provider-catalog.js';
|
|
12
|
-
export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-
|
|
12
|
+
export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-cluster max-[760px]:grid-cols-1';
|
|
13
13
|
export const PROVIDER_SURFACE_CLASS = 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';
|
|
14
14
|
export function ProviderGrid({ workspaceSlug, providers, isPending, isFetching = false, error, onRetry, emptyMessage, loadingLabel = 'Loading providers', errorSubject = 'available integrations', onOpenProvider }) {
|
|
15
15
|
const installableProviders = providers.filter((provider)=>PROVIDER_CATALOG[provider.provider]);
|
|
@@ -18,7 +18,7 @@ export function ProviderGrid({ workspaceSlug, providers, isPending, isFetching =
|
|
|
18
18
|
});
|
|
19
19
|
if (error) {
|
|
20
20
|
return /*#__PURE__*/ _jsx("div", {
|
|
21
|
-
className: cn(PROVIDER_SURFACE_CLASS, 'px-
|
|
21
|
+
className: cn(PROVIDER_SURFACE_CLASS, 'px-row'),
|
|
22
22
|
children: /*#__PURE__*/ _jsx(QueryLoadError, {
|
|
23
23
|
query: {
|
|
24
24
|
isError: true,
|
|
@@ -33,7 +33,7 @@ export function ProviderGrid({ workspaceSlug, providers, isPending, isFetching =
|
|
|
33
33
|
}
|
|
34
34
|
if (installableProviders.length === 0) {
|
|
35
35
|
return /*#__PURE__*/ _jsx("div", {
|
|
36
|
-
className: cn(PROVIDER_SURFACE_CLASS, 'px-
|
|
36
|
+
className: cn(PROVIDER_SURFACE_CLASS, 'px-row'),
|
|
37
37
|
children: /*#__PURE__*/ _jsx(EmptyState, {
|
|
38
38
|
icon: "componentLine",
|
|
39
39
|
title: "No integrations available",
|
|
@@ -60,7 +60,7 @@ function ProviderCard({ provider, workspaceSlug, onOpenProvider }) {
|
|
|
60
60
|
type: "button",
|
|
61
61
|
"aria-label": `Add ${provider.displayName}`,
|
|
62
62
|
onClick: ()=>onOpenProvider?.(provider.provider),
|
|
63
|
-
className: "group flex h-full w-full min-w-0 items-center justify-between gap-
|
|
63
|
+
className: "group flex h-full w-full min-w-0 items-center justify-between gap-cluster rounded-8 border border-border-neutral-base bg-background-neutral-base p-panel-compact text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none",
|
|
64
64
|
children: /*#__PURE__*/ _jsx(ProviderCardContent, {
|
|
65
65
|
provider: provider,
|
|
66
66
|
action: "Add"
|
|
@@ -73,7 +73,7 @@ function ProviderCard({ provider, workspaceSlug, onOpenProvider }) {
|
|
|
73
73
|
workspaceSlug
|
|
74
74
|
},
|
|
75
75
|
"aria-label": `Install ${provider.displayName}`,
|
|
76
|
-
className: "group flex h-full min-w-0 items-center justify-between gap-
|
|
76
|
+
className: "group flex h-full min-w-0 items-center justify-between gap-cluster rounded-8 border border-border-neutral-base bg-background-neutral-base p-panel-compact transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none",
|
|
77
77
|
children: /*#__PURE__*/ _jsx(ProviderCardContent, {
|
|
78
78
|
provider: provider,
|
|
79
79
|
action: "Install"
|
|
@@ -84,7 +84,7 @@ function ProviderCardContent({ provider, action }) {
|
|
|
84
84
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
85
85
|
children: [
|
|
86
86
|
/*#__PURE__*/ _jsxs("span", {
|
|
87
|
-
className: "flex min-w-0 items-center gap-
|
|
87
|
+
className: "flex min-w-0 items-center gap-cluster",
|
|
88
88
|
children: [
|
|
89
89
|
/*#__PURE__*/ _jsx(IntegrationIcon, {
|
|
90
90
|
source: provider.provider,
|
|
@@ -101,7 +101,7 @@ function ProviderCardContent({ provider, action }) {
|
|
|
101
101
|
]
|
|
102
102
|
}),
|
|
103
103
|
/*#__PURE__*/ _jsxs("span", {
|
|
104
|
-
className: "flex shrink-0 items-center gap-
|
|
104
|
+
className: "flex shrink-0 items-center gap-tight text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive",
|
|
105
105
|
children: [
|
|
106
106
|
/*#__PURE__*/ _jsx(Text, {
|
|
107
107
|
as: "span",
|
|
@@ -129,12 +129,12 @@ function ProviderGridSkeleton({ label }) {
|
|
|
129
129
|
3
|
|
130
130
|
].map((tile)=>/*#__PURE__*/ _jsx("li", {
|
|
131
131
|
children: /*#__PURE__*/ _jsx(Card, {
|
|
132
|
-
className: "h-full p-
|
|
132
|
+
className: "h-full p-panel-compact",
|
|
133
133
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
134
|
-
className: "flex items-center justify-between gap-
|
|
134
|
+
className: "flex items-center justify-between gap-cluster",
|
|
135
135
|
children: [
|
|
136
136
|
/*#__PURE__*/ _jsxs("div", {
|
|
137
|
-
className: "flex min-w-0 items-center gap-
|
|
137
|
+
className: "flex min-w-0 items-center gap-cluster",
|
|
138
138
|
children: [
|
|
139
139
|
/*#__PURE__*/ _jsx(Skeleton, {
|
|
140
140
|
className: "size-24 shrink-0"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/provider-grid.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IntegrationIcon} from '@shipfox/integration-icons';\nimport {Card} from '@shipfox/react-ui/card';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport type {IntegrationProvider} from '#core/models.js';\nimport {PROVIDER_CATALOG} from '#provider-catalog.js';\n\nexport interface ProviderGridProps {\n workspaceSlug: string;\n providers: IntegrationProvider[];\n isPending: boolean;\n isFetching?: boolean;\n error?: Error | null | undefined;\n onRetry?: () => void;\n emptyMessage: string;\n loadingLabel?: string;\n errorSubject?: string;\n onOpenProvider?: ((provider: string) => void) | undefined;\n}\n\nexport const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-
|
|
1
|
+
{"version":3,"sources":["../../src/components/provider-grid.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IntegrationIcon} from '@shipfox/integration-icons';\nimport {Card} from '@shipfox/react-ui/card';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {Link} from '@tanstack/react-router';\nimport type {IntegrationProvider} from '#core/models.js';\nimport {PROVIDER_CATALOG} from '#provider-catalog.js';\n\nexport interface ProviderGridProps {\n workspaceSlug: string;\n providers: IntegrationProvider[];\n isPending: boolean;\n isFetching?: boolean;\n error?: Error | null | undefined;\n onRetry?: () => void;\n emptyMessage: string;\n loadingLabel?: string;\n errorSubject?: string;\n onOpenProvider?: ((provider: string) => void) | undefined;\n}\n\nexport const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-cluster max-[760px]:grid-cols-1';\n\nexport const PROVIDER_SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function ProviderGrid({\n workspaceSlug,\n providers,\n isPending,\n isFetching = false,\n error,\n onRetry,\n emptyMessage,\n loadingLabel = 'Loading providers',\n errorSubject = 'available integrations',\n onOpenProvider,\n}: ProviderGridProps) {\n const installableProviders = providers.filter((provider) => PROVIDER_CATALOG[provider.provider]);\n\n if (isPending) return <ProviderGridSkeleton label={loadingLabel} />;\n\n if (error) {\n return (\n <div className={cn(PROVIDER_SURFACE_CLASS, 'px-row')}>\n <QueryLoadError\n query={{\n isError: true,\n isFetching,\n data: undefined,\n error,\n refetch: onRetry ?? (() => undefined),\n }}\n subject={errorSubject}\n />\n </div>\n );\n }\n\n if (installableProviders.length === 0) {\n return (\n <div className={cn(PROVIDER_SURFACE_CLASS, 'px-row')}>\n <EmptyState\n icon=\"componentLine\"\n title=\"No integrations available\"\n description={emptyMessage}\n />\n </div>\n );\n }\n\n return (\n <ul className={PROVIDER_GRID_CLASS}>\n {installableProviders.map((provider) => (\n <li key={provider.provider}>\n <ProviderCard\n provider={provider}\n workspaceSlug={workspaceSlug}\n onOpenProvider={onOpenProvider}\n />\n </li>\n ))}\n </ul>\n );\n}\n\nfunction ProviderCard({\n provider,\n workspaceSlug,\n onOpenProvider,\n}: {\n provider: IntegrationProvider;\n workspaceSlug: string;\n onOpenProvider?: ((provider: string) => void) | undefined;\n}) {\n const catalog = PROVIDER_CATALOG[provider.provider];\n if (!catalog) return null;\n\n if (catalog.kind === 'modal-connect') {\n return (\n <button\n type=\"button\"\n aria-label={`Add ${provider.displayName}`}\n onClick={() => onOpenProvider?.(provider.provider)}\n className=\"group flex h-full w-full min-w-0 items-center justify-between gap-cluster rounded-8 border border-border-neutral-base bg-background-neutral-base p-panel-compact text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none\"\n >\n <ProviderCardContent provider={provider} action=\"Add\" />\n </button>\n );\n }\n\n return (\n <Link\n to={catalog.setupPath}\n params={{workspaceSlug}}\n aria-label={`Install ${provider.displayName}`}\n className=\"group flex h-full min-w-0 items-center justify-between gap-cluster rounded-8 border border-border-neutral-base bg-background-neutral-base p-panel-compact transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus focus-visible:outline-none\"\n >\n <ProviderCardContent provider={provider} action=\"Install\" />\n </Link>\n );\n}\n\nfunction ProviderCardContent({\n provider,\n action,\n}: {\n provider: IntegrationProvider;\n action: 'Add' | 'Install';\n}) {\n return (\n <>\n <span className=\"flex min-w-0 items-center gap-cluster\">\n <IntegrationIcon\n source={provider.provider}\n aria-hidden\n className=\"size-24 shrink-0 text-foreground-neutral-base\"\n />\n <Text as=\"span\" size=\"md\" bold className=\"truncate\">\n {provider.displayName}\n </Text>\n </span>\n <span className=\"flex shrink-0 items-center gap-tight text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive\">\n <Text as=\"span\" size=\"sm\">\n {action}\n </Text>\n <Icon name=\"chevronRight\" className=\"size-16\" />\n </span>\n </>\n );\n}\n\nfunction ProviderGridSkeleton({label}: {label: string}) {\n return (\n <ul role=\"status\" aria-label={label} className={PROVIDER_GRID_CLASS}>\n {[0, 1, 2, 3].map((tile) => (\n <li key={tile}>\n <Card className=\"h-full p-panel-compact\">\n <div className=\"flex items-center justify-between gap-cluster\">\n <div className=\"flex min-w-0 items-center gap-cluster\">\n <Skeleton className=\"size-24 shrink-0\" />\n <Skeleton className=\"h-16 w-100\" />\n </div>\n <Skeleton className=\"h-16 w-64 shrink-0\" />\n </div>\n </Card>\n </li>\n ))}\n </ul>\n );\n}\n"],"names":["QueryLoadError","IntegrationIcon","Card","EmptyState","Icon","Skeleton","Text","cn","Link","PROVIDER_CATALOG","PROVIDER_GRID_CLASS","PROVIDER_SURFACE_CLASS","ProviderGrid","workspaceSlug","providers","isPending","isFetching","error","onRetry","emptyMessage","loadingLabel","errorSubject","onOpenProvider","installableProviders","filter","provider","ProviderGridSkeleton","label","div","className","query","isError","data","undefined","refetch","subject","length","icon","title","description","ul","map","li","ProviderCard","catalog","kind","button","type","aria-label","displayName","onClick","ProviderCardContent","action","to","setupPath","params","span","source","aria-hidden","as","size","bold","name","role","tile"],"mappings":"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"}
|
|
@@ -37,7 +37,7 @@ export function RedirectInstallPage({ installRequest, errorFallbackMessage, load
|
|
|
37
37
|
]);
|
|
38
38
|
if (errorMessage) {
|
|
39
39
|
return /*#__PURE__*/ _jsxs("div", {
|
|
40
|
-
className: "mx-auto flex w-full max-w-[480px] flex-col gap-
|
|
40
|
+
className: "mx-auto flex w-full max-w-[480px] flex-col gap-group",
|
|
41
41
|
children: [
|
|
42
42
|
/*#__PURE__*/ _jsx(Callout, {
|
|
43
43
|
role: "alert",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/redirect-install-page.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {useActiveWorkspace} from '@shipfox/client-auth';\nimport {ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useRef, useState} from 'react';\nimport type {InstallRedirect} from '#core/models.js';\n\ninterface RedirectInstallPageProps {\n installRequest: (body: {workspace_id: string}) => Promise<InstallRedirect>;\n errorFallbackMessage: string;\n loadingLabel?: string;\n /**\n * Runs before leaving the app (e.g. to persist the workspace id for a\n * state-less provider callback. It must not throw. A failed side effect\n * should never block the redirect.\n */\n beforeRedirect?: (workspaceId: string) => void;\n /** Injectable for tests: jsdom's window.location cannot be stubbed. */\n assignLocation?: (url: string) => void;\n}\n\nexport function RedirectInstallPage({\n installRequest,\n errorFallbackMessage,\n loadingLabel = 'Starting installation',\n beforeRedirect,\n assignLocation = (url) => window.location.assign(url),\n}: RedirectInstallPageProps) {\n const workspace = useActiveWorkspace();\n const startedRef = useRef(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>();\n\n useEffect(() => {\n if (startedRef.current) return;\n startedRef.current = true;\n // The side effect is best-effort persistence; a throw here must never\n // block the install redirect, so swallow it and continue.\n try {\n beforeRedirect?.(workspace.id);\n } catch {\n // ignore\n }\n installRequest({workspace_id: workspace.id})\n .then((response) => {\n assignLocation(response.installUrl);\n })\n .catch((error: unknown) => {\n setErrorMessage(error instanceof ApiError ? error.message : errorFallbackMessage);\n });\n }, [workspace, installRequest, beforeRedirect, errorFallbackMessage, assignLocation]);\n\n if (errorMessage) {\n return (\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col gap-
|
|
1
|
+
{"version":3,"sources":["../../src/components/redirect-install-page.tsx"],"sourcesContent":["import {ApiError} from '@shipfox/client-api';\nimport {useActiveWorkspace} from '@shipfox/client-auth';\nimport {ButtonLink} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FullPageLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {Link} from '@tanstack/react-router';\nimport {useEffect, useRef, useState} from 'react';\nimport type {InstallRedirect} from '#core/models.js';\n\ninterface RedirectInstallPageProps {\n installRequest: (body: {workspace_id: string}) => Promise<InstallRedirect>;\n errorFallbackMessage: string;\n loadingLabel?: string;\n /**\n * Runs before leaving the app (e.g. to persist the workspace id for a\n * state-less provider callback. It must not throw. A failed side effect\n * should never block the redirect.\n */\n beforeRedirect?: (workspaceId: string) => void;\n /** Injectable for tests: jsdom's window.location cannot be stubbed. */\n assignLocation?: (url: string) => void;\n}\n\nexport function RedirectInstallPage({\n installRequest,\n errorFallbackMessage,\n loadingLabel = 'Starting installation',\n beforeRedirect,\n assignLocation = (url) => window.location.assign(url),\n}: RedirectInstallPageProps) {\n const workspace = useActiveWorkspace();\n const startedRef = useRef(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>();\n\n useEffect(() => {\n if (startedRef.current) return;\n startedRef.current = true;\n // The side effect is best-effort persistence; a throw here must never\n // block the install redirect, so swallow it and continue.\n try {\n beforeRedirect?.(workspace.id);\n } catch {\n // ignore\n }\n installRequest({workspace_id: workspace.id})\n .then((response) => {\n assignLocation(response.installUrl);\n })\n .catch((error: unknown) => {\n setErrorMessage(error instanceof ApiError ? error.message : errorFallbackMessage);\n });\n }, [workspace, installRequest, beforeRedirect, errorFallbackMessage, assignLocation]);\n\n if (errorMessage) {\n return (\n <div className=\"mx-auto flex w-full max-w-[480px] flex-col gap-group\">\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{errorMessage}</Text>\n </Callout>\n <ButtonLink asChild variant=\"muted\" className=\"w-fit\">\n <Link to=\"/w/$workspaceSlug/integrations\" params={{workspaceSlug: workspace.slug}}>\n Back to integrations\n </Link>\n </ButtonLink>\n </div>\n );\n }\n\n return <FullPageLoader aria-label={loadingLabel} />;\n}\n"],"names":["ApiError","useActiveWorkspace","ButtonLink","Callout","FullPageLoader","Text","Link","useEffect","useRef","useState","RedirectInstallPage","installRequest","errorFallbackMessage","loadingLabel","beforeRedirect","assignLocation","url","window","location","assign","workspace","startedRef","errorMessage","setErrorMessage","current","id","workspace_id","then","response","installUrl","catch","error","message","div","className","role","type","size","asChild","variant","to","params","workspaceSlug","slug","aria-label"],"mappings":";AAAA,SAAQA,QAAQ,QAAO,sBAAsB;AAC7C,SAAQC,kBAAkB,QAAO,uBAAuB;AACxD,SAAQC,UAAU,QAAO,2BAA2B;AACpD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,cAAc,QAAO,2BAA2B;AACxD,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AAiBlD,OAAO,SAASC,oBAAoB,EAClCC,cAAc,EACdC,oBAAoB,EACpBC,eAAe,uBAAuB,EACtCC,cAAc,EACdC,iBAAiB,CAACC,MAAQC,OAAOC,QAAQ,CAACC,MAAM,CAACH,IAAI,EAC5B;IACzB,MAAMI,YAAYnB;IAClB,MAAMoB,aAAab,OAAO;IAC1B,MAAM,CAACc,cAAcC,gBAAgB,GAAGd;IAExCF,UAAU;QACR,IAAIc,WAAWG,OAAO,EAAE;QACxBH,WAAWG,OAAO,GAAG;QACrB,sEAAsE;QACtE,0DAA0D;QAC1D,IAAI;YACFV,iBAAiBM,UAAUK,EAAE;QAC/B,EAAE,OAAM;QACN,SAAS;QACX;QACAd,eAAe;YAACe,cAAcN,UAAUK,EAAE;QAAA,GACvCE,IAAI,CAAC,CAACC;YACLb,eAAea,SAASC,UAAU;QACpC,GACCC,KAAK,CAAC,CAACC;YACNR,gBAAgBQ,iBAAiB/B,WAAW+B,MAAMC,OAAO,GAAGpB;QAC9D;IACJ,GAAG;QAACQ;QAAWT;QAAgBG;QAAgBF;QAAsBG;KAAe;IAEpF,IAAIO,cAAc;QAChB,qBACE,MAACW;YAAIC,WAAU;;8BACb,KAAC/B;oBAAQgC,MAAK;oBAAQC,MAAK;8BACzB,cAAA,KAAC/B;wBAAKgC,MAAK;kCAAMf;;;8BAEnB,KAACpB;oBAAWoC,OAAO;oBAACC,SAAQ;oBAAQL,WAAU;8BAC5C,cAAA,KAAC5B;wBAAKkC,IAAG;wBAAiCC,QAAQ;4BAACC,eAAetB,UAAUuB,IAAI;wBAAA;kCAAG;;;;;IAM3F;IAEA,qBAAO,KAACvC;QAAewC,cAAY/B;;AACrC"}
|
|
@@ -8,7 +8,7 @@ import { Skeleton } from '@shipfox/react-ui/skeleton';
|
|
|
8
8
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
|
|
9
9
|
import { Text } from '@shipfox/react-ui/typography';
|
|
10
10
|
import { useId } from 'react';
|
|
11
|
-
const REPOSITORY_GRID_CLASS_NAME = 'grid grid-cols-2 gap-
|
|
11
|
+
const REPOSITORY_GRID_CLASS_NAME = 'grid grid-cols-2 gap-inline max-[760px]:grid-cols-1';
|
|
12
12
|
const REPOSITORY_SKELETON_WIDTHS = [
|
|
13
13
|
'w-64',
|
|
14
14
|
'w-96',
|
|
@@ -19,7 +19,7 @@ export function RepositoryPicker({ repositories, selectedRepositoryId, onSelect,
|
|
|
19
19
|
const labelId = useId();
|
|
20
20
|
const showSearch = onSearchChange !== undefined;
|
|
21
21
|
return /*#__PURE__*/ _jsxs("div", {
|
|
22
|
-
className: "flex flex-col gap-
|
|
22
|
+
className: "flex flex-col gap-inline",
|
|
23
23
|
children: [
|
|
24
24
|
/*#__PURE__*/ _jsx(Label, {
|
|
25
25
|
id: labelId,
|
|
@@ -36,7 +36,7 @@ export function RepositoryPicker({ repositories, selectedRepositoryId, onSelect,
|
|
|
36
36
|
}) : null,
|
|
37
37
|
isLoading ? /*#__PURE__*/ _jsx(RepositoryLoadingState, {}) : null,
|
|
38
38
|
!isLoading && repositories.length === 0 ? /*#__PURE__*/ _jsx("div", {
|
|
39
|
-
className: "rounded-8 border border-border-neutral-base bg-background-subtle-base p-
|
|
39
|
+
className: "rounded-8 border border-border-neutral-base bg-background-subtle-base p-panel-compact",
|
|
40
40
|
children: /*#__PURE__*/ _jsx(Text, {
|
|
41
41
|
size: "sm",
|
|
42
42
|
children: emptyMessage
|
|
@@ -101,7 +101,7 @@ function RepositoryLoadingState() {
|
|
|
101
101
|
"aria-hidden": "true",
|
|
102
102
|
className: REPOSITORY_GRID_CLASS_NAME,
|
|
103
103
|
children: REPOSITORY_SKELETON_WIDTHS.map((width)=>/*#__PURE__*/ _jsx("div", {
|
|
104
|
-
className: "h-50 min-w-0 rounded-8 border border-border-neutral-base bg-background-neutral-base p-
|
|
104
|
+
className: "h-50 min-w-0 rounded-8 border border-border-neutral-base bg-background-neutral-base p-[14px]",
|
|
105
105
|
children: /*#__PURE__*/ _jsx(Skeleton, {
|
|
106
106
|
className: `h-20 ${width}`
|
|
107
107
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/repository-picker.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {useIsTextTruncated} from '@shipfox/react-ui/hooks';\nimport {Input} from '@shipfox/react-ui/input';\nimport {Label} from '@shipfox/react-ui/label';\nimport {RadioGroup, RadioGroupItem} from '@shipfox/react-ui/radio-group';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useId} from 'react';\nimport type {Repository} from '#core/models.js';\n\nconst REPOSITORY_GRID_CLASS_NAME = 'grid grid-cols-2 gap-
|
|
1
|
+
{"version":3,"sources":["../../src/components/repository-picker.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {useIsTextTruncated} from '@shipfox/react-ui/hooks';\nimport {Input} from '@shipfox/react-ui/input';\nimport {Label} from '@shipfox/react-ui/label';\nimport {RadioGroup, RadioGroupItem} from '@shipfox/react-ui/radio-group';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useId} from 'react';\nimport type {Repository} from '#core/models.js';\n\nconst REPOSITORY_GRID_CLASS_NAME = 'grid grid-cols-2 gap-inline max-[760px]:grid-cols-1';\nconst REPOSITORY_SKELETON_WIDTHS = ['w-64', 'w-96', 'w-80', 'w-112'] as const;\n\nexport function RepositoryPicker({\n repositories,\n selectedRepositoryId,\n onSelect,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n onLoadMore,\n emptyMessage = 'No repositories found.',\n searchValue,\n onSearchChange,\n searchDisabled,\n}: {\n repositories: Repository[];\n selectedRepositoryId: string | undefined;\n onSelect: (repositoryId: string) => void;\n isLoading: boolean;\n isFetchingNextPage?: boolean;\n hasNextPage?: boolean;\n onLoadMore?: () => void;\n emptyMessage?: string;\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n searchDisabled?: boolean;\n}) {\n const labelId = useId();\n const showSearch = onSearchChange !== undefined;\n\n return (\n <div className=\"flex flex-col gap-inline\">\n <Label id={labelId} className=\"sr-only\">\n Repository\n </Label>\n\n {showSearch ? (\n <Input\n type=\"search\"\n placeholder=\"Search repositories…\"\n aria-label=\"Search repositories\"\n value={searchValue ?? ''}\n onChange={(event) => onSearchChange?.(event.target.value)}\n disabled={searchDisabled}\n />\n ) : null}\n\n {isLoading ? <RepositoryLoadingState /> : null}\n\n {!isLoading && repositories.length === 0 ? (\n <div className=\"rounded-8 border border-border-neutral-base bg-background-subtle-base p-panel-compact\">\n <Text size=\"sm\">{emptyMessage}</Text>\n </div>\n ) : null}\n\n {repositories.length > 0 ? (\n <RadioGroup\n aria-labelledby={labelId}\n value={selectedRepositoryId ?? ''}\n onValueChange={onSelect}\n className={REPOSITORY_GRID_CLASS_NAME}\n >\n {repositories.map((repository) => (\n <RepositoryCard key={repository.externalRepositoryId} repository={repository} />\n ))}\n </RadioGroup>\n ) : null}\n\n {hasNextPage && onLoadMore ? (\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n isLoading={isFetchingNextPage ?? false}\n onClick={onLoadMore}\n >\n Load more\n </Button>\n ) : null}\n </div>\n );\n}\n\nfunction RepositoryCard({repository}: {repository: Repository}) {\n const {ref: nameRef, isTruncated} = useIsTextTruncated<HTMLSpanElement>(repository.name);\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <RadioGroupItem value={repository.externalRepositoryId} className=\"min-w-0\">\n <span ref={nameRef} className=\"block min-w-0 truncate\">\n <Text as=\"span\" size=\"sm\" bold>\n {repository.name}\n </Text>\n </span>\n </RadioGroupItem>\n </TooltipTrigger>\n {isTruncated ? <TooltipContent>{repository.name}</TooltipContent> : null}\n </Tooltip>\n );\n}\n\nfunction RepositoryLoadingState() {\n return (\n <>\n <div role=\"status\" className=\"sr-only\">\n Loading repositories.\n </div>\n <div aria-hidden=\"true\" className={REPOSITORY_GRID_CLASS_NAME}>\n {/* The skeleton mirrors RadioGroupItem's own 14px padding contract so the\n placeholder and the loaded card stay the same height. */}\n {REPOSITORY_SKELETON_WIDTHS.map((width) => (\n <div\n key={width}\n className=\"h-50 min-w-0 rounded-8 border border-border-neutral-base bg-background-neutral-base p-[14px]\"\n >\n <Skeleton className={`h-20 ${width}`} />\n </div>\n ))}\n </div>\n </>\n );\n}\n"],"names":["Button","useIsTextTruncated","Input","Label","RadioGroup","RadioGroupItem","Skeleton","Tooltip","TooltipContent","TooltipTrigger","Text","useId","REPOSITORY_GRID_CLASS_NAME","REPOSITORY_SKELETON_WIDTHS","RepositoryPicker","repositories","selectedRepositoryId","onSelect","isLoading","isFetchingNextPage","hasNextPage","onLoadMore","emptyMessage","searchValue","onSearchChange","searchDisabled","labelId","showSearch","undefined","div","className","id","type","placeholder","aria-label","value","onChange","event","target","disabled","RepositoryLoadingState","length","size","aria-labelledby","onValueChange","map","repository","RepositoryCard","externalRepositoryId","variant","onClick","ref","nameRef","isTruncated","name","asChild","span","as","bold","role","aria-hidden","width"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,kBAAkB,QAAO,0BAA0B;AAC3D,SAAQC,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,UAAU,EAAEC,cAAc,QAAO,gCAAgC;AACzE,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,KAAK,QAAO,QAAQ;AAG5B,MAAMC,6BAA6B;AACnC,MAAMC,6BAA6B;IAAC;IAAQ;IAAQ;IAAQ;CAAQ;AAEpE,OAAO,SAASC,iBAAiB,EAC/BC,YAAY,EACZC,oBAAoB,EACpBC,QAAQ,EACRC,SAAS,EACTC,kBAAkB,EAClBC,WAAW,EACXC,UAAU,EACVC,eAAe,wBAAwB,EACvCC,WAAW,EACXC,cAAc,EACdC,cAAc,EAaf;IACC,MAAMC,UAAUf;IAChB,MAAMgB,aAAaH,mBAAmBI;IAEtC,qBACE,MAACC;QAAIC,WAAU;;0BACb,KAAC3B;gBAAM4B,IAAIL;gBAASI,WAAU;0BAAU;;YAIvCH,2BACC,KAACzB;gBACC8B,MAAK;gBACLC,aAAY;gBACZC,cAAW;gBACXC,OAAOZ,eAAe;gBACtBa,UAAU,CAACC,QAAUb,iBAAiBa,MAAMC,MAAM,CAACH,KAAK;gBACxDI,UAAUd;iBAEV;YAEHP,0BAAY,KAACsB,8BAA4B;YAEzC,CAACtB,aAAaH,aAAa0B,MAAM,KAAK,kBACrC,KAACZ;gBAAIC,WAAU;0BACb,cAAA,KAACpB;oBAAKgC,MAAK;8BAAMpB;;iBAEjB;YAEHP,aAAa0B,MAAM,GAAG,kBACrB,KAACrC;gBACCuC,mBAAiBjB;gBACjBS,OAAOnB,wBAAwB;gBAC/B4B,eAAe3B;gBACfa,WAAWlB;0BAEVG,aAAa8B,GAAG,CAAC,CAACC,2BACjB,KAACC;wBAAqDD,YAAYA;uBAA7CA,WAAWE,oBAAoB;iBAGtD;YAEH5B,eAAeC,2BACd,KAACrB;gBACCgC,MAAK;gBACLiB,SAAQ;gBACRP,MAAK;gBACLxB,WAAWC,sBAAsB;gBACjC+B,SAAS7B;0BACV;iBAGC;;;AAGV;AAEA,SAAS0B,eAAe,EAACD,UAAU,EAA2B;IAC5D,MAAM,EAACK,KAAKC,OAAO,EAAEC,WAAW,EAAC,GAAGpD,mBAAoC6C,WAAWQ,IAAI;IAEvF,qBACE,MAAC/C;;0BACC,KAACE;gBAAe8C,OAAO;0BACrB,cAAA,KAAClD;oBAAe8B,OAAOW,WAAWE,oBAAoB;oBAAElB,WAAU;8BAChE,cAAA,KAAC0B;wBAAKL,KAAKC;wBAAStB,WAAU;kCAC5B,cAAA,KAACpB;4BAAK+C,IAAG;4BAAOf,MAAK;4BAAKgB,IAAI;sCAC3BZ,WAAWQ,IAAI;;;;;YAKvBD,4BAAc,KAAC7C;0BAAgBsC,WAAWQ,IAAI;iBAAqB;;;AAG1E;AAEA,SAASd;IACP,qBACE;;0BACE,KAACX;gBAAI8B,MAAK;gBAAS7B,WAAU;0BAAU;;0BAGvC,KAACD;gBAAI+B,eAAY;gBAAO9B,WAAWlB;0BAGhCC,2BAA2BgC,GAAG,CAAC,CAACgB,sBAC/B,KAAChC;wBAECC,WAAU;kCAEV,cAAA,KAACxB;4BAASwB,WAAW,CAAC,KAAK,EAAE+B,OAAO;;uBAH/BA;;;;AASjB"}
|
|
@@ -29,15 +29,15 @@ export function CopyableValue({ label, value, note, className }) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
return /*#__PURE__*/ _jsxs("div", {
|
|
32
|
-
className: cn('flex w-full min-w-0 flex-col gap-
|
|
32
|
+
className: cn('flex w-full min-w-0 flex-col gap-inline', className),
|
|
33
33
|
children: [
|
|
34
34
|
/*#__PURE__*/ _jsxs("div", {
|
|
35
|
-
className: "flex min-w-0 items-center gap-
|
|
35
|
+
className: "flex min-w-0 items-center gap-inline",
|
|
36
36
|
children: [
|
|
37
37
|
/*#__PURE__*/ _jsx(Code, {
|
|
38
38
|
as: "span",
|
|
39
39
|
variant: "paragraph",
|
|
40
|
-
className: "min-w-0 flex-1 break-all rounded-4 border border-border-neutral-base bg-background-components-base px-
|
|
40
|
+
className: "min-w-0 flex-1 break-all rounded-4 border border-border-neutral-base bg-background-components-base px-tight py-[6px] text-foreground-neutral-base",
|
|
41
41
|
children: value
|
|
42
42
|
}),
|
|
43
43
|
/*#__PURE__*/ _jsx(Button, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/webhook/copyable-value.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {useCopyToClipboard} from '@shipfox/react-ui/hooks';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport type {ReactNode} from 'react';\nimport {useEffect, useRef, useState} from 'react';\n\ninterface CopyableValueProps {\n label: string;\n value: string;\n note?: ReactNode;\n className?: string;\n}\n\nexport function CopyableValue({label, value, note, className}: CopyableValueProps) {\n const [copied, setCopied] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const {copy} = useCopyToClipboard({\n text: value,\n onCopy: () => {\n setCopied(true);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => setCopied(false), 2000);\n },\n });\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n async function handleCopy() {\n try {\n await copy();\n } catch {\n toast.error('Could not copy.');\n }\n }\n\n return (\n <div className={cn('flex w-full min-w-0 flex-col gap-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/webhook/copyable-value.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {useCopyToClipboard} from '@shipfox/react-ui/hooks';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport type {ReactNode} from 'react';\nimport {useEffect, useRef, useState} from 'react';\n\ninterface CopyableValueProps {\n label: string;\n value: string;\n note?: ReactNode;\n className?: string;\n}\n\nexport function CopyableValue({label, value, note, className}: CopyableValueProps) {\n const [copied, setCopied] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const {copy} = useCopyToClipboard({\n text: value,\n onCopy: () => {\n setCopied(true);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => setCopied(false), 2000);\n },\n });\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n async function handleCopy() {\n try {\n await copy();\n } catch {\n toast.error('Could not copy.');\n }\n }\n\n return (\n <div className={cn('flex w-full min-w-0 flex-col gap-inline', className)}>\n <div className=\"flex min-w-0 items-center gap-inline\">\n <Code\n as=\"span\"\n variant=\"paragraph\"\n className=\"min-w-0 flex-1 break-all rounded-4 border border-border-neutral-base bg-background-components-base px-tight py-[6px] text-foreground-neutral-base\"\n >\n {value}\n </Code>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n iconLeft={copied ? 'check' : 'copy'}\n aria-label={`Copy ${label}`}\n onClick={() => {\n void handleCopy();\n }}\n >\n Copy\n </Button>\n </div>\n {note ? (\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n {note}\n </Text>\n ) : null}\n </div>\n );\n}\n"],"names":["Button","useCopyToClipboard","toast","Code","Text","cn","useEffect","useRef","useState","CopyableValue","label","value","note","className","copied","setCopied","timeoutRef","undefined","copy","text","onCopy","current","clearTimeout","setTimeout","handleCopy","error","div","as","variant","type","size","iconLeft","aria-label","onClick"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,kBAAkB,QAAO,0BAA0B;AAC3D,SAAQC,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,IAAI,EAAEC,IAAI,QAAO,+BAA+B;AACxD,SAAQC,EAAE,QAAO,0BAA0B;AAE3C,SAAQC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AASlD,OAAO,SAASC,cAAc,EAACC,KAAK,EAAEC,KAAK,EAAEC,IAAI,EAAEC,SAAS,EAAqB;IAC/E,MAAM,CAACC,QAAQC,UAAU,GAAGP,SAAS;IACrC,MAAMQ,aAAaT,OAAkDU;IACrE,MAAM,EAACC,IAAI,EAAC,GAAGjB,mBAAmB;QAChCkB,MAAMR;QACNS,QAAQ;YACNL,UAAU;YACV,IAAIC,WAAWK,OAAO,EAAEC,aAAaN,WAAWK,OAAO;YACvDL,WAAWK,OAAO,GAAGE,WAAW,IAAMR,UAAU,QAAQ;QAC1D;IACF;IAEAT,UAAU;QACR,OAAO;YACL,IAAIU,WAAWK,OAAO,EAAEC,aAAaN,WAAWK,OAAO;QACzD;IACF,GAAG,EAAE;IAEL,eAAeG;QACb,IAAI;YACF,MAAMN;QACR,EAAE,OAAM;YACNhB,MAAMuB,KAAK,CAAC;QACd;IACF;IAEA,qBACE,MAACC;QAAIb,WAAWR,GAAG,2CAA2CQ;;0BAC5D,MAACa;gBAAIb,WAAU;;kCACb,KAACV;wBACCwB,IAAG;wBACHC,SAAQ;wBACRf,WAAU;kCAETF;;kCAEH,KAACX;wBACC6B,MAAK;wBACLD,SAAQ;wBACRE,MAAK;wBACLC,UAAUjB,SAAS,UAAU;wBAC7BkB,cAAY,CAAC,KAAK,EAAEtB,OAAO;wBAC3BuB,SAAS;4BACP,KAAKT;wBACP;kCACD;;;;YAIFZ,qBACC,KAACR;gBAAK0B,MAAK;gBAAKjB,WAAU;0BACvBD;iBAED;;;AAGV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/webhook/webhook-create-modal.tsx"],"sourcesContent":["import {\n createWebhookConnectionBodySchema,\n WEBHOOK_RESERVED_SLUGS,\n webhookSlugSchema,\n} from '@shipfox/api-integration-webhook-dto';\nimport {displayNameFieldError} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '@shipfox/react-ui/modal';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useEffect, useRef, useState} from 'react';\nimport type {IntegrationConnection, WebhookConnection} from '#core/models.js';\nimport {useCreateWebhookConnectionMutation} from '#hooks/api/webhook-connections.js';\nimport {webhookCreateErrorToFormError} from './webhook-form-errors.js';\n\ninterface WebhookCreateModalProps {\n workspaceId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (connection: IntegrationConnection) => void;\n}\n\nexport function WebhookCreateModal({\n workspaceId,\n open,\n onOpenChange,\n onCreated,\n}: WebhookCreateModalProps) {\n const createWebhook = useCreateWebhookConnectionMutation();\n const [formError, setFormError] = useState<string | undefined>();\n const [hasManualSlug, setHasManualSlug] = useState(false);\n const nameInputRef = useRef<HTMLInputElement | null>(null);\n\n const form = useForm({\n defaultValues: {name: '', slug: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n const body = createWebhookConnectionBodySchema.parse({\n workspace_id: workspaceId,\n name: value.name.trim(),\n slug: value.slug.trim(),\n });\n const connection = await createWebhook.mutateAsync(body);\n onCreated(webhookConnectionToIntegrationConnection(connection));\n toast.success('Webhook created.');\n onOpenChange(false);\n } catch (error) {\n const mapped = webhookCreateErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n useEffect(() => {\n if (!open) {\n setFormError(undefined);\n setHasManualSlug(false);\n form.reset();\n return;\n }\n requestAnimationFrame(() => nameInputRef.current?.focus());\n }, [form, open]);\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (createWebhook.isPending && !nextOpen) return;\n onOpenChange(nextOpen);\n };\n\n return (\n <Modal open={open} onOpenChange={handleOpenChange}>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Add webhook</ModalTitle>\n <ModalHeader title=\"Add webhook\" showClose={!createWebhook.isPending} />\n <form\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <ModalBody className=\"gap-16\">\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Create a named inbound webhook URL for this workspace.\n </Text>\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n {formError}\n </Callout>\n ) : null}\n <form.Field\n name=\"name\"\n validators={{\n onBlur: ({value}) => webhookNameFieldError(value),\n onSubmit: ({value}) => webhookNameFieldError(value),\n }}\n >\n {(field) => (\n <FormField\n label=\"Name\"\n id=\"webhook-name\"\n error={fieldError(field)}\n className=\"w-full\"\n >\n <FormFieldInput\n ref={nameInputRef}\n name=\"name\"\n value={field.state.value}\n onChange={(event) => {\n const nextName = event.target.value;\n field.handleChange(nextName);\n if (!hasManualSlug) {\n form.setFieldValue(\n 'slug',\n nextName.trim() ? suggestWebhookSlug(nextName) : '',\n );\n }\n }}\n onBlur={field.handleBlur}\n placeholder=\"Stripe production\"\n disabled={createWebhook.isPending}\n />\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"slug\"\n validators={{\n onBlur: ({value}) => webhookSlugFieldError(value),\n onSubmit: ({value}) => webhookSlugFieldError(value),\n }}\n >\n {(field) => (\n <FormField\n label=\"Slug\"\n id=\"webhook-slug\"\n error={fieldError(field)}\n className=\"w-full\"\n >\n <FormFieldInput\n name=\"slug\"\n value={field.state.value}\n onChange={(event) => {\n const nextSlug = event.target.value;\n setHasManualSlug(nextSlug.trim().length > 0);\n field.handleChange(nextSlug);\n if (nextSlug.trim().length === 0 && form.state.values.name.trim()) {\n form.setFieldValue('slug', suggestWebhookSlug(form.state.values.name));\n }\n }}\n onBlur={field.handleBlur}\n placeholder=\"webhook-stripe-production\"\n disabled={createWebhook.isPending}\n />\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Reference in workflows with{' '}\n <Code as=\"span\">\n source: {field.state.value || 'webhook-stripe-production'}\n </Code>\n .\n </Text>\n </FormField>\n )}\n </form.Field>\n </ModalBody>\n <ModalFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={createWebhook.isPending}\n onClick={() => onOpenChange(false)}\n >\n Cancel\n </Button>\n <Button type=\"submit\" isLoading={createWebhook.isPending}>\n Create\n </Button>\n </ModalFooter>\n </form>\n </ModalContent>\n </Modal>\n );\n}\n\nfunction webhookNameFieldError(value: string): string | undefined {\n return displayNameFieldError(\n value.trim(),\n 'Webhook name',\n createWebhookConnectionBodySchema.shape.name,\n );\n}\n\nfunction webhookSlugFieldError(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return 'Slug is required.';\n if (WEBHOOK_RESERVED_SLUGS.includes(trimmed as (typeof WEBHOOK_RESERVED_SLUGS)[number])) {\n return 'That slug is reserved.';\n }\n if (webhookSlugSchema.safeParse(trimmed).success) return undefined;\n return 'Use lowercase letters, numbers, hyphens, or underscores.';\n}\n\nfunction suggestWebhookSlug(name: string): string {\n const prefix = 'webhook';\n const suffix = name\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/g, '-')\n .replaceAll(/^-+|-+$/g, '')\n .slice(0, 100 - prefix.length - 1)\n .replaceAll(/-+$/g, '');\n\n return suffix ? `${prefix}-${suffix}` : prefix;\n}\n\nfunction webhookConnectionToIntegrationConnection(\n connection: WebhookConnection,\n): IntegrationConnection {\n return {\n id: connection.id,\n workspaceId: connection.workspaceId,\n provider: 'webhook',\n externalAccountId: connection.slug,\n slug: connection.slug,\n displayName: connection.name,\n lifecycleStatus: connection.lifecycleStatus,\n capabilities: [],\n createdAt: connection.createdAt,\n updatedAt: connection.updatedAt,\n };\n}\n"],"names":["createWebhookConnectionBodySchema","WEBHOOK_RESERVED_SLUGS","webhookSlugSchema","displayNameFieldError","Button","Callout","FormField","FormFieldInput","fieldError","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","toast","Code","Text","useForm","useEffect","useRef","useState","useCreateWebhookConnectionMutation","webhookCreateErrorToFormError","WebhookCreateModal","workspaceId","open","onOpenChange","onCreated","createWebhook","formError","setFormError","hasManualSlug","setHasManualSlug","nameInputRef","form","defaultValues","name","slug","onSubmit","value","undefined","body","parse","workspace_id","trim","connection","mutateAsync","webhookConnectionToIntegrationConnection","success","error","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","reset","requestAnimationFrame","current","focus","handleOpenChange","nextOpen","isPending","aria-describedby","className","title","showClose","noValidate","event","preventDefault","stopPropagation","handleSubmit","size","role","type","Field","validators","onBlur","webhookNameFieldError","label","id","ref","state","onChange","nextName","target","handleChange","setFieldValue","suggestWebhookSlug","handleBlur","placeholder","disabled","webhookSlugFieldError","nextSlug","length","values","as","variant","onClick","isLoading","shape","trimmed","includes","safeParse","prefix","suffix","toLowerCase","replaceAll","slice","provider","externalAccountId","displayName","lifecycleStatus","capabilities","createdAt","updatedAt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/webhook/webhook-create-modal.tsx"],"sourcesContent":["import {\n createWebhookConnectionBodySchema,\n WEBHOOK_RESERVED_SLUGS,\n webhookSlugSchema,\n} from '@shipfox/api-integration-webhook-dto';\nimport {displayNameFieldError} from '@shipfox/client-ui';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '@shipfox/react-ui/modal';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useEffect, useRef, useState} from 'react';\nimport type {IntegrationConnection, WebhookConnection} from '#core/models.js';\nimport {useCreateWebhookConnectionMutation} from '#hooks/api/webhook-connections.js';\nimport {webhookCreateErrorToFormError} from './webhook-form-errors.js';\n\ninterface WebhookCreateModalProps {\n workspaceId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreated: (connection: IntegrationConnection) => void;\n}\n\nexport function WebhookCreateModal({\n workspaceId,\n open,\n onOpenChange,\n onCreated,\n}: WebhookCreateModalProps) {\n const createWebhook = useCreateWebhookConnectionMutation();\n const [formError, setFormError] = useState<string | undefined>();\n const [hasManualSlug, setHasManualSlug] = useState(false);\n const nameInputRef = useRef<HTMLInputElement | null>(null);\n\n const form = useForm({\n defaultValues: {name: '', slug: ''},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n const body = createWebhookConnectionBodySchema.parse({\n workspace_id: workspaceId,\n name: value.name.trim(),\n slug: value.slug.trim(),\n });\n const connection = await createWebhook.mutateAsync(body);\n onCreated(webhookConnectionToIntegrationConnection(connection));\n toast.success('Webhook created.');\n onOpenChange(false);\n } catch (error) {\n const mapped = webhookCreateErrorToFormError(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n } else {\n setFormError(mapped.message);\n }\n }\n },\n });\n\n useEffect(() => {\n if (!open) {\n setFormError(undefined);\n setHasManualSlug(false);\n form.reset();\n return;\n }\n requestAnimationFrame(() => nameInputRef.current?.focus());\n }, [form, open]);\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (createWebhook.isPending && !nextOpen) return;\n onOpenChange(nextOpen);\n };\n\n return (\n <Modal open={open} onOpenChange={handleOpenChange}>\n <ModalContent aria-describedby={undefined}>\n <ModalTitle className=\"sr-only\">Add webhook</ModalTitle>\n <ModalHeader title=\"Add webhook\" showClose={!createWebhook.isPending} />\n <form\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <ModalBody className=\"gap-group\">\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Create a named inbound webhook URL for this workspace.\n </Text>\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n {formError}\n </Callout>\n ) : null}\n <form.Field\n name=\"name\"\n validators={{\n onBlur: ({value}) => webhookNameFieldError(value),\n onSubmit: ({value}) => webhookNameFieldError(value),\n }}\n >\n {(field) => (\n <FormField\n label=\"Name\"\n id=\"webhook-name\"\n error={fieldError(field)}\n className=\"w-full\"\n >\n <FormFieldInput\n ref={nameInputRef}\n name=\"name\"\n value={field.state.value}\n onChange={(event) => {\n const nextName = event.target.value;\n field.handleChange(nextName);\n if (!hasManualSlug) {\n form.setFieldValue(\n 'slug',\n nextName.trim() ? suggestWebhookSlug(nextName) : '',\n );\n }\n }}\n onBlur={field.handleBlur}\n placeholder=\"Stripe production\"\n disabled={createWebhook.isPending}\n />\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"slug\"\n validators={{\n onBlur: ({value}) => webhookSlugFieldError(value),\n onSubmit: ({value}) => webhookSlugFieldError(value),\n }}\n >\n {(field) => (\n <FormField\n label=\"Slug\"\n id=\"webhook-slug\"\n error={fieldError(field)}\n className=\"w-full\"\n >\n <FormFieldInput\n name=\"slug\"\n value={field.state.value}\n onChange={(event) => {\n const nextSlug = event.target.value;\n setHasManualSlug(nextSlug.trim().length > 0);\n field.handleChange(nextSlug);\n if (nextSlug.trim().length === 0 && form.state.values.name.trim()) {\n form.setFieldValue('slug', suggestWebhookSlug(form.state.values.name));\n }\n }}\n onBlur={field.handleBlur}\n placeholder=\"webhook-stripe-production\"\n disabled={createWebhook.isPending}\n />\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Reference in workflows with{' '}\n <Code as=\"span\">\n source: {field.state.value || 'webhook-stripe-production'}\n </Code>\n .\n </Text>\n </FormField>\n )}\n </form.Field>\n </ModalBody>\n <ModalFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={createWebhook.isPending}\n onClick={() => onOpenChange(false)}\n >\n Cancel\n </Button>\n <Button type=\"submit\" isLoading={createWebhook.isPending}>\n Create\n </Button>\n </ModalFooter>\n </form>\n </ModalContent>\n </Modal>\n );\n}\n\nfunction webhookNameFieldError(value: string): string | undefined {\n return displayNameFieldError(\n value.trim(),\n 'Webhook name',\n createWebhookConnectionBodySchema.shape.name,\n );\n}\n\nfunction webhookSlugFieldError(value: string): string | undefined {\n const trimmed = value.trim();\n if (trimmed.length === 0) return 'Slug is required.';\n if (WEBHOOK_RESERVED_SLUGS.includes(trimmed as (typeof WEBHOOK_RESERVED_SLUGS)[number])) {\n return 'That slug is reserved.';\n }\n if (webhookSlugSchema.safeParse(trimmed).success) return undefined;\n return 'Use lowercase letters, numbers, hyphens, or underscores.';\n}\n\nfunction suggestWebhookSlug(name: string): string {\n const prefix = 'webhook';\n const suffix = name\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/g, '-')\n .replaceAll(/^-+|-+$/g, '')\n .slice(0, 100 - prefix.length - 1)\n .replaceAll(/-+$/g, '');\n\n return suffix ? `${prefix}-${suffix}` : prefix;\n}\n\nfunction webhookConnectionToIntegrationConnection(\n connection: WebhookConnection,\n): IntegrationConnection {\n return {\n id: connection.id,\n workspaceId: connection.workspaceId,\n provider: 'webhook',\n externalAccountId: connection.slug,\n slug: connection.slug,\n displayName: connection.name,\n lifecycleStatus: connection.lifecycleStatus,\n capabilities: [],\n createdAt: connection.createdAt,\n updatedAt: connection.updatedAt,\n };\n}\n"],"names":["createWebhookConnectionBodySchema","WEBHOOK_RESERVED_SLUGS","webhookSlugSchema","displayNameFieldError","Button","Callout","FormField","FormFieldInput","fieldError","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","toast","Code","Text","useForm","useEffect","useRef","useState","useCreateWebhookConnectionMutation","webhookCreateErrorToFormError","WebhookCreateModal","workspaceId","open","onOpenChange","onCreated","createWebhook","formError","setFormError","hasManualSlug","setHasManualSlug","nameInputRef","form","defaultValues","name","slug","onSubmit","value","undefined","body","parse","workspace_id","trim","connection","mutateAsync","webhookConnectionToIntegrationConnection","success","error","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","reset","requestAnimationFrame","current","focus","handleOpenChange","nextOpen","isPending","aria-describedby","className","title","showClose","noValidate","event","preventDefault","stopPropagation","handleSubmit","size","role","type","Field","validators","onBlur","webhookNameFieldError","label","id","ref","state","onChange","nextName","target","handleChange","setFieldValue","suggestWebhookSlug","handleBlur","placeholder","disabled","webhookSlugFieldError","nextSlug","length","values","as","variant","onClick","isLoading","shape","trimmed","includes","safeParse","prefix","suffix","toLowerCase","replaceAll","slice","provider","externalAccountId","displayName","lifecycleStatus","capabilities","createdAt","updatedAt"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-modals.stories.d.ts","sourceRoot":"","sources":["../../../src/components/webhook/webhook-modals.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAsBrD,KAAK,QAAQ,GACT,aAAa,GACb,gBAAgB,GAChB,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAoCD,iBAAS,iBAAiB,CAAC,EAAC,QAAQ,EAAC,EAAE,sBAAsB,+BAoB5D;AAED,QAAA,MAAM,IAAI
|
|
1
|
+
{"version":3,"file":"webhook-modals.stories.d.ts","sourceRoot":"","sources":["../../../src/components/webhook/webhook-modals.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAsBrD,KAAK,QAAQ,GACT,aAAa,GACb,gBAAgB,GAChB,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAoCD,iBAAS,iBAAiB,CAAC,EAAC,QAAQ,EAAC,EAAE,sBAAsB,+BAoB5D;AAED,QAAA,MAAM,IAAI;;;;QAGK,MAAM;;;;;CAEqB,CAAC;eAE5B,IAAI;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAAU,CAAC;AAEpC,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAEhC,CAAC"}
|
|
@@ -27,9 +27,9 @@ export function WebhookUsageDetails({ workspaceId, connectionId }) {
|
|
|
27
27
|
}
|
|
28
28
|
if (!connection) return null;
|
|
29
29
|
return /*#__PURE__*/ _jsx("div", {
|
|
30
|
-
className: "flex w-full flex-col gap-
|
|
30
|
+
className: "flex w-full flex-col gap-group",
|
|
31
31
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
32
|
-
className: "flex w-full min-w-0 flex-col gap-
|
|
32
|
+
className: "flex w-full min-w-0 flex-col gap-inline",
|
|
33
33
|
children: [
|
|
34
34
|
/*#__PURE__*/ _jsx(Text, {
|
|
35
35
|
size: "sm",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/webhook/webhook-usage-details.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useWebhookConnectionsQuery} from '#hooks/api/webhook-connections.js';\nimport {CopyableValue} from './copyable-value.js';\nimport {WebhookPublicEndpointAlert} from './webhook-public-endpoint-alert.js';\n\ninterface WebhookUsageDetailsProps {\n workspaceId: string;\n connectionId: string;\n}\n\nexport function WebhookUsageDetails({workspaceId, connectionId}: WebhookUsageDetailsProps) {\n const connectionsQuery = useWebhookConnectionsQuery(workspaceId);\n const connection = connectionsQuery.data?.find((candidate) => candidate.id === connectionId);\n\n if (connectionsQuery.isPending) {\n return (\n <div className=\"flex min-h-80 items-center justify-center\">\n <ShipfoxLoader size={32} animation=\"circular\" color=\"orange\" background=\"light\" />\n </div>\n );\n }\n\n if (connectionsQuery.isError && connectionsQuery.data === undefined) {\n return <QueryLoadError query={connectionsQuery} subject=\"webhook details\" />;\n }\n\n if (!connection) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/webhook/webhook-usage-details.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {ShipfoxLoader} from '@shipfox/react-ui/loader';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useWebhookConnectionsQuery} from '#hooks/api/webhook-connections.js';\nimport {CopyableValue} from './copyable-value.js';\nimport {WebhookPublicEndpointAlert} from './webhook-public-endpoint-alert.js';\n\ninterface WebhookUsageDetailsProps {\n workspaceId: string;\n connectionId: string;\n}\n\nexport function WebhookUsageDetails({workspaceId, connectionId}: WebhookUsageDetailsProps) {\n const connectionsQuery = useWebhookConnectionsQuery(workspaceId);\n const connection = connectionsQuery.data?.find((candidate) => candidate.id === connectionId);\n\n if (connectionsQuery.isPending) {\n return (\n <div className=\"flex min-h-80 items-center justify-center\">\n <ShipfoxLoader size={32} animation=\"circular\" color=\"orange\" background=\"light\" />\n </div>\n );\n }\n\n if (connectionsQuery.isError && connectionsQuery.data === undefined) {\n return <QueryLoadError query={connectionsQuery} subject=\"webhook details\" />;\n }\n\n if (!connection) return null;\n\n return (\n <div className=\"flex w-full flex-col gap-group\">\n <div className=\"flex w-full min-w-0 flex-col gap-inline\">\n <Text size=\"sm\" bold>\n Inbound URL\n </Text>\n <CopyableValue label=\"inbound URL\" value={connection.inboundUrl} />\n <WebhookPublicEndpointAlert />\n </div>\n </div>\n );\n}\n"],"names":["QueryLoadError","ShipfoxLoader","Text","useWebhookConnectionsQuery","CopyableValue","WebhookPublicEndpointAlert","WebhookUsageDetails","workspaceId","connectionId","connectionsQuery","connection","data","find","candidate","id","isPending","div","className","size","animation","color","background","isError","undefined","query","subject","bold","label","value","inboundUrl"],"mappings":";AAAA,SAAQA,cAAc,QAAO,qBAAqB;AAClD,SAAQC,aAAa,QAAO,2BAA2B;AACvD,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,0BAA0B,QAAO,oCAAoC;AAC7E,SAAQC,aAAa,QAAO,sBAAsB;AAClD,SAAQC,0BAA0B,QAAO,qCAAqC;AAO9E,OAAO,SAASC,oBAAoB,EAACC,WAAW,EAAEC,YAAY,EAA2B;IACvF,MAAMC,mBAAmBN,2BAA2BI;IACpD,MAAMG,aAAaD,iBAAiBE,IAAI,EAAEC,KAAK,CAACC,YAAcA,UAAUC,EAAE,KAAKN;IAE/E,IAAIC,iBAAiBM,SAAS,EAAE;QAC9B,qBACE,KAACC;YAAIC,WAAU;sBACb,cAAA,KAAChB;gBAAciB,MAAM;gBAAIC,WAAU;gBAAWC,OAAM;gBAASC,YAAW;;;IAG9E;IAEA,IAAIZ,iBAAiBa,OAAO,IAAIb,iBAAiBE,IAAI,KAAKY,WAAW;QACnE,qBAAO,KAACvB;YAAewB,OAAOf;YAAkBgB,SAAQ;;IAC1D;IAEA,IAAI,CAACf,YAAY,OAAO;IAExB,qBACE,KAACM;QAAIC,WAAU;kBACb,cAAA,MAACD;YAAIC,WAAU;;8BACb,KAACf;oBAAKgB,MAAK;oBAAKQ,IAAI;8BAAC;;8BAGrB,KAACtB;oBAAcuB,OAAM;oBAAcC,OAAOlB,WAAWmB,UAAU;;8BAC/D,KAACxB;;;;AAIT"}
|
package/dist/feature.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare const integrationsSettingsSections: readonly [{
|
|
2
|
-
readonly id:
|
|
3
|
-
readonly pathSegment:
|
|
4
|
-
readonly label:
|
|
5
|
-
readonly icon:
|
|
2
|
+
readonly id: 'settings.integrations';
|
|
3
|
+
readonly pathSegment: 'integrations';
|
|
4
|
+
readonly label: 'Integrations';
|
|
5
|
+
readonly icon: 'plugLine';
|
|
6
6
|
readonly order: 700;
|
|
7
7
|
}];
|
|
8
8
|
export declare const integrationsFeature: {
|
|
@@ -61,10 +61,10 @@ export declare const integrationsFeature: {
|
|
|
61
61
|
readonly impl: "@shipfox/client-integrations/routes/integrations-settings";
|
|
62
62
|
}];
|
|
63
63
|
readonly settingsSections: readonly [{
|
|
64
|
-
readonly id:
|
|
65
|
-
readonly pathSegment:
|
|
66
|
-
readonly label:
|
|
67
|
-
readonly icon:
|
|
64
|
+
readonly id: 'settings.integrations';
|
|
65
|
+
readonly pathSegment: 'integrations';
|
|
66
|
+
readonly label: 'Integrations';
|
|
67
|
+
readonly icon: 'plugLine';
|
|
68
68
|
readonly order: 700;
|
|
69
69
|
}];
|
|
70
70
|
};
|
package/dist/feature.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../src/feature.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B
|
|
1
|
+
{"version":3,"file":"feature.d.ts","sourceRoot":"","sources":["../src/feature.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B;iBAEjC,uBAAuB;0BACd,cAAc;oBACpB,cAAc;mBACf,UAAU;oBACT,GAAG;EAEsC,CAAC;AAErD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBARxB,uBAAuB;8BACd,cAAc;wBACpB,cAAc;uBACf,UAAU;wBACT,GAAG;;CA0EZ,CAAC"}
|