@flamingo-stack/openframe-frontend-core 0.0.201 → 0.0.202-snapshot.20260521221224
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/dist/{chunk-OII2IERE.cjs → chunk-25LVV26X.cjs} +4 -4
- package/dist/chunk-25LVV26X.cjs.map +1 -0
- package/dist/{chunk-UCY537V4.cjs → chunk-3YH2M76N.cjs} +1565 -1146
- package/dist/chunk-3YH2M76N.cjs.map +1 -0
- package/dist/{chunk-55HF462A.js → chunk-CPXLQ57U.js} +6 -7
- package/dist/chunk-CPXLQ57U.js.map +1 -0
- package/dist/{chunk-CSW5GYBU.js → chunk-E6Q6UGDK.js} +4603 -4184
- package/dist/chunk-E6Q6UGDK.js.map +1 -0
- package/dist/{chunk-3B43AHYE.cjs → chunk-RMB5DVED.cjs} +6 -7
- package/dist/chunk-RMB5DVED.cjs.map +1 -0
- package/dist/{chunk-4ML3NA2L.js → chunk-XGL5FKIK.js} +4 -4
- package/dist/chunk-XGL5FKIK.js.map +1 -0
- package/dist/components/chat/approval-request-message.d.ts.map +1 -1
- package/dist/components/chat/chat-container.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/chat-ticket-item.d.ts.map +1 -1
- package/dist/components/chat/types/message.types.d.ts +34 -0
- package/dist/components/chat/types/message.types.d.ts.map +1 -1
- package/dist/components/features/index.cjs +16 -4
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.d.ts +1 -0
- package/dist/components/features/index.d.ts.map +1 -1
- package/dist/components/features/index.js +17 -5
- package/dist/components/features/select-button.d.ts.map +1 -1
- package/dist/components/index.cjs +18 -4
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +17 -3
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/navigation/navigation-sidebar.d.ts.map +1 -1
- package/dist/components/providers/theme-provider.d.ts +69 -0
- package/dist/components/providers/theme-provider.d.ts.map +1 -0
- package/dist/components/resizable.d.ts +1 -1
- package/dist/components/ui/button/split-button.d.ts.map +1 -1
- package/dist/components/ui/data-table/data-table-row.d.ts +16 -4
- package/dist/components/ui/data-table/data-table-row.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +52 -52
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +3 -3
- package/dist/components/ui/file-manager/index.js.map +1 -1
- package/dist/components/ui/floating-tooltip.d.ts +3 -1
- package/dist/components/ui/floating-tooltip.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +6 -4
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +5 -3
- package/dist/components/ui/input-trigger.d.ts.map +1 -1
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/components/ui/ticket-info-section.d.ts.map +1 -1
- package/dist/components/ui/ticket-note-card.d.ts.map +1 -1
- package/dist/components/ui/truncate-text.d.ts +33 -0
- package/dist/components/ui/truncate-text.d.ts.map +1 -0
- package/dist/components/user-summary-stub.d.ts.map +1 -1
- package/dist/hooks/index.cjs +2 -2
- package/dist/hooks/index.js +1 -1
- package/dist/index.cjs +18 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +17 -3
- package/package.json +2 -1
- package/src/components/chat/approval-request-message.tsx +106 -92
- package/src/components/chat/chat-container.tsx +10 -6
- package/src/components/chat/chat-message-enhanced.tsx +51 -9
- package/src/components/chat/chat-message-list.tsx +27 -19
- package/src/components/chat/chat-ticket-item.tsx +2 -3
- package/src/components/chat/types/message.types.ts +35 -0
- package/src/components/features/board/ticket-card.tsx +2 -2
- package/src/components/features/filters-dropdown.tsx +1 -1
- package/src/components/features/index.ts +15 -0
- package/src/components/features/notifications/notification-tile.tsx +2 -2
- package/src/components/features/policy-configuration-panel.tsx +1 -1
- package/src/components/features/push-button-selector.tsx +1 -1
- package/src/components/features/select-button.tsx +2 -3
- package/src/components/features/video-bites-display.tsx +1 -1
- package/src/components/features/waitlist-form.tsx +1 -1
- package/src/components/filter-chip.tsx +1 -1
- package/src/components/layout/title-block.tsx +2 -2
- package/src/components/navigation/header-organization-filter.tsx +1 -1
- package/src/components/navigation/navigation-sidebar.tsx +107 -54
- package/src/components/platform/ScriptInfoSection.tsx +1 -1
- package/src/components/providers/theme-provider.tsx +130 -0
- package/src/components/shared/onboarding/onboarding-step-card.tsx +2 -2
- package/src/components/shared/product-release/product-release-card.tsx +6 -6
- package/src/components/shared/product-release/release-detail-page.tsx +1 -1
- package/src/components/ui/assignee-dropdown.tsx +3 -3
- package/src/components/ui/autocomplete.tsx +2 -2
- package/src/components/ui/button/split-button.tsx +3 -5
- package/src/components/ui/checkbox-block.tsx +1 -1
- package/src/components/ui/data-table/data-table-row.tsx +82 -48
- package/src/components/ui/device-card-compact.tsx +2 -2
- package/src/components/ui/device-card.tsx +2 -2
- package/src/components/ui/entity-image.tsx +1 -1
- package/src/components/ui/field-wrapper.tsx +1 -1
- package/src/components/ui/file-manager/file-manager-table-row.tsx +2 -2
- package/src/components/ui/file-upload.tsx +2 -2
- package/src/components/ui/filter-list.tsx +1 -1
- package/src/components/ui/floating-tooltip.tsx +9 -5
- package/src/components/ui/hidden-tags-popup.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/info-card.tsx +2 -2
- package/src/components/ui/input-trigger.tsx +1 -2
- package/src/components/ui/organization-card.tsx +3 -3
- package/src/components/ui/radio-group.tsx +2 -3
- package/src/components/ui/search-input.tsx +2 -2
- package/src/components/ui/service-card.tsx +3 -3
- package/src/components/ui/simple-markdown-renderer.tsx +248 -2
- package/src/components/ui/tag.tsx +1 -1
- package/src/components/ui/tags-manager.tsx +2 -2
- package/src/components/ui/ticket-attachments-list.tsx +1 -1
- package/src/components/ui/ticket-info-section.tsx +2 -3
- package/src/components/ui/ticket-note-card.tsx +4 -1
- package/src/components/ui/toaster.tsx +3 -3
- package/src/components/ui/truncate-text.tsx +116 -0
- package/src/components/user-summary-stub.tsx +32 -26
- package/src/components/vendor-display-button.tsx +1 -1
- package/src/stories/SplitButton.stories.tsx +7 -1
- package/src/stories/Theme.stories.tsx +350 -0
- package/src/styles/README.md +271 -174
- package/src/styles/dark_theme.tokens.json +982 -0
- package/src/styles/light_theme.tokens.json +982 -0
- package/src/styles/ods-colors.css +225 -146
- package/src/styles/ods_color_tokens.json +1 -300
- package/dist/chunk-3B43AHYE.cjs.map +0 -1
- package/dist/chunk-4ML3NA2L.js.map +0 -1
- package/dist/chunk-55HF462A.js.map +0 -1
- package/dist/chunk-CSW5GYBU.js.map +0 -1
- package/dist/chunk-OII2IERE.cjs.map +0 -1
- package/dist/chunk-UCY537V4.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import Link from 'next/link'
|
|
4
|
-
import React, { memo, useCallback, type ReactNode } from 'react'
|
|
4
|
+
import React, { memo, useCallback, useRef, type ReactNode } from 'react'
|
|
5
5
|
import { flexRender, type Row } from '@tanstack/react-table'
|
|
6
6
|
import { cn } from '../../../utils/cn'
|
|
7
7
|
import { ROW_HEIGHT_DESKTOP } from './data-table-skeleton'
|
|
@@ -19,16 +19,28 @@ export interface DataTableRowProps<T> {
|
|
|
19
19
|
/**
|
|
20
20
|
* Click-bubbling protocol: any element inside a cell that should NOT trigger
|
|
21
21
|
* `onRowClick` / row navigation must carry the `data-no-row-click` attribute.
|
|
22
|
-
* The row checks `target.closest('[data-no-row-click]')`
|
|
23
|
-
* `onClick
|
|
24
|
-
*
|
|
22
|
+
* The row checks `target.closest('[data-no-row-click]')` and short-circuits:
|
|
23
|
+
* in `onClick` mode it skips the consumer's handler; in link mode (when
|
|
24
|
+
* `href` is set) it calls `e.preventDefault()` so `<Link>` does not navigate.
|
|
25
|
+
*
|
|
26
|
+
* Clicks originating from portaled descendants (e.g. `FloatingTooltip`,
|
|
27
|
+
* dropdown menus rendered through `FloatingPortal`) bubble through React's
|
|
28
|
+
* component tree and reach this handler, but their DOM target lives outside
|
|
29
|
+
* the row subtree. The handler ignores any click whose target is not
|
|
30
|
+
* physically contained within the row element — no `stopPropagation`
|
|
31
|
+
* required at the source.
|
|
32
|
+
*
|
|
33
|
+
* In link mode the row IS the `<Link>` — content lives inside it, not under
|
|
34
|
+
* an absolute overlay — so native browser link behaviour works: hover,
|
|
35
|
+
* right-click "Open in new tab", middle-click, `Cmd+click`, focus outlines,
|
|
36
|
+
* `:visited` styles, etc.
|
|
25
37
|
*
|
|
26
38
|
* Example column with action buttons:
|
|
27
39
|
* ```tsx
|
|
28
40
|
* {
|
|
29
41
|
* id: 'actions',
|
|
30
42
|
* cell: ({ row }) => (
|
|
31
|
-
* <div data-no-row-click className="flex gap-2 justify-end
|
|
43
|
+
* <div data-no-row-click className="flex gap-2 justify-end">
|
|
32
44
|
* <Button onClick={() => edit(row.original)}>Edit</Button>
|
|
33
45
|
* </div>
|
|
34
46
|
* ),
|
|
@@ -49,61 +61,83 @@ function DataTableRowImpl<T>({
|
|
|
49
61
|
className,
|
|
50
62
|
}: DataTableRowProps<T>) {
|
|
51
63
|
const isLinkMode = Boolean(href) && !onClick
|
|
64
|
+
const containerRef = useRef<HTMLElement | null>(null)
|
|
52
65
|
|
|
53
66
|
const handleClick = useCallback(
|
|
54
67
|
(e: React.MouseEvent) => {
|
|
55
68
|
const target = e.target as HTMLElement
|
|
56
|
-
|
|
69
|
+
// React-bubbled events from portaled descendants (tooltips, dropdowns, etc.)
|
|
70
|
+
// reach this handler even though their DOM target lives outside the row.
|
|
71
|
+
// Suppress them — and in link mode, preventDefault so `<Link>` does not navigate.
|
|
72
|
+
if (!containerRef.current?.contains(target)) {
|
|
73
|
+
if (isLinkMode) e.preventDefault()
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
if (target.closest('[data-no-row-click]')) {
|
|
77
|
+
if (isLinkMode) e.preventDefault()
|
|
78
|
+
return
|
|
79
|
+
}
|
|
57
80
|
onClick?.(row.original)
|
|
58
81
|
},
|
|
59
|
-
[onClick, row.original],
|
|
82
|
+
[onClick, row.original, isLinkMode],
|
|
60
83
|
)
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
const containerClassName = cn(
|
|
86
|
+
'block rounded-md bg-ods-card border border-ods-border overflow-hidden no-underline text-inherit',
|
|
87
|
+
(onClick || isLinkMode) && 'cursor-pointer hover:bg-ods-bg-active transition-colors',
|
|
88
|
+
className,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const cells = (
|
|
63
92
|
<div
|
|
64
93
|
className={cn(
|
|
65
|
-
'
|
|
66
|
-
|
|
67
|
-
'cursor-pointer hover:bg-ods-bg-active transition-colors',
|
|
68
|
-
className,
|
|
94
|
+
'flex items-center gap-[var(--spacing-system-mf)] px-[var(--spacing-system-mf)]',
|
|
95
|
+
compact ? 'py-[var(--spacing-system-xsf)]' : `py-0 ${ROW_HEIGHT_DESKTOP}`,
|
|
69
96
|
)}
|
|
70
|
-
onClick={isLinkMode ? undefined : handleClick}
|
|
71
97
|
>
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
{row.getVisibleCells().map(cell => {
|
|
99
|
+
const meta = cell.column.columnDef.meta
|
|
100
|
+
return (
|
|
101
|
+
<div
|
|
102
|
+
key={cell.id}
|
|
103
|
+
className={cn(
|
|
104
|
+
'flex flex-col overflow-hidden',
|
|
105
|
+
alignJustify(meta?.align),
|
|
106
|
+
meta?.width || 'flex-1 min-w-0',
|
|
107
|
+
meta?.cellClassName,
|
|
108
|
+
getHideClasses(meta?.hideAt),
|
|
109
|
+
)}
|
|
110
|
+
>
|
|
111
|
+
<CellContent>
|
|
112
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
113
|
+
</CellContent>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
})}
|
|
117
|
+
</div>
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if (isLinkMode && href) {
|
|
121
|
+
return (
|
|
122
|
+
<Link
|
|
123
|
+
href={href}
|
|
124
|
+
prefetch={false}
|
|
125
|
+
ref={containerRef as React.RefObject<HTMLAnchorElement>}
|
|
126
|
+
className={containerClassName}
|
|
127
|
+
onClick={handleClick}
|
|
86
128
|
>
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
>
|
|
100
|
-
<CellContent>
|
|
101
|
-
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
102
|
-
</CellContent>
|
|
103
|
-
</div>
|
|
104
|
-
)
|
|
105
|
-
})}
|
|
106
|
-
</div>
|
|
129
|
+
{cells}
|
|
130
|
+
</Link>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div
|
|
136
|
+
ref={containerRef as React.RefObject<HTMLDivElement>}
|
|
137
|
+
className={containerClassName}
|
|
138
|
+
onClick={onClick ? handleClick : undefined}
|
|
139
|
+
>
|
|
140
|
+
{cells}
|
|
107
141
|
</div>
|
|
108
142
|
)
|
|
109
143
|
}
|
|
@@ -114,7 +148,7 @@ export const DataTableRow = memo(DataTableRowImpl) as typeof DataTableRowImpl
|
|
|
114
148
|
function CellContent({ children }: { children: ReactNode }) {
|
|
115
149
|
if (typeof children === 'string' || typeof children === 'number') {
|
|
116
150
|
return (
|
|
117
|
-
<span className="text-h4 text-ods-text-primary truncate">{children}</span>
|
|
151
|
+
<span className="text-h4 text-ods-text-primary truncate" title={String(children)}>{children}</span>
|
|
118
152
|
)
|
|
119
153
|
}
|
|
120
154
|
return <>{children}</>
|
|
@@ -35,12 +35,12 @@ export function DeviceCardCompact({
|
|
|
35
35
|
{...props}
|
|
36
36
|
>
|
|
37
37
|
{hasName && (
|
|
38
|
-
<span className="font-['DM_Sans'] font-medium text-[16px] leading-[20px] text-ods-text-primary truncate">
|
|
38
|
+
<span className="font-['DM_Sans'] font-medium text-[16px] leading-[20px] text-ods-text-primary truncate" title={deviceName}>
|
|
39
39
|
{deviceName}
|
|
40
40
|
</span>
|
|
41
41
|
)}
|
|
42
42
|
{hasOrg && (
|
|
43
|
-
<span className="font-['DM_Sans'] font-medium text-[14px] leading-[18px] text-ods-text-secondary truncate">
|
|
43
|
+
<span className="font-['DM_Sans'] font-medium text-[14px] leading-[18px] text-ods-text-secondary truncate" title={organization}>
|
|
44
44
|
{organization}
|
|
45
45
|
</span>
|
|
46
46
|
)}
|
|
@@ -103,12 +103,12 @@ export function DeviceCard({
|
|
|
103
103
|
className="shrink-0"
|
|
104
104
|
/>
|
|
105
105
|
)}
|
|
106
|
-
<span className="text-h4 text-ods-text-primary truncate">
|
|
106
|
+
<span className="text-h4 text-ods-text-primary truncate" title={device.name}>
|
|
107
107
|
{device.name}
|
|
108
108
|
</span>
|
|
109
109
|
</div>
|
|
110
110
|
{device.organization && (
|
|
111
|
-
<span className="font-['DM_Sans'] font-medium text-[14px] leading-[20px] text-ods-text-secondary truncate">
|
|
111
|
+
<span className="font-['DM_Sans'] font-medium text-[14px] leading-[20px] text-ods-text-secondary truncate" title={device.organization}>
|
|
112
112
|
{device.organization}
|
|
113
113
|
</span>
|
|
114
114
|
)}
|
|
@@ -48,7 +48,7 @@ export function EntityImage({ src, alt, fallbackText, className }: EntityImagePr
|
|
|
48
48
|
alt={alt ?? ''}
|
|
49
49
|
onError={() => setImageFailed(true)}
|
|
50
50
|
className={cn(
|
|
51
|
-
'size-[52px] md:size-[60px] shrink-0 rounded-md border border-ods-border object-
|
|
51
|
+
'size-[52px] md:size-[60px] shrink-0 rounded-md border border-ods-border object-contain',
|
|
52
52
|
className,
|
|
53
53
|
)}
|
|
54
54
|
/>
|
|
@@ -33,7 +33,7 @@ const FieldWrapper = React.forwardRef<HTMLDivElement, FieldWrapperProps>(
|
|
|
33
33
|
)}
|
|
34
34
|
{children}
|
|
35
35
|
{error && (
|
|
36
|
-
<p className={cn("absolute bottom-0 left-0 right-0 translate-y-full text-h6 truncate", errorVariantClasses[errorVariant])}>
|
|
36
|
+
<p className={cn("absolute bottom-0 left-0 right-0 translate-y-full text-h6 truncate", errorVariantClasses[errorVariant])} title={error}>
|
|
37
37
|
{error}
|
|
38
38
|
</p>
|
|
39
39
|
)}
|
|
@@ -76,11 +76,11 @@ export function FileManagerTableRow({
|
|
|
76
76
|
size="md"
|
|
77
77
|
/>
|
|
78
78
|
<div className="flex flex-col min-w-0">
|
|
79
|
-
<span className="text-sm text-ods-text-primary truncate">
|
|
79
|
+
<span className="text-sm text-ods-text-primary truncate" title={file.name}>
|
|
80
80
|
{file.name}
|
|
81
81
|
</span>
|
|
82
82
|
{showPath && file.path && (
|
|
83
|
-
<span className="text-xs text-ods-text-secondary truncate">
|
|
83
|
+
<span className="text-xs text-ods-text-secondary truncate" title={file.path}>
|
|
84
84
|
{file.path}
|
|
85
85
|
</span>
|
|
86
86
|
)}
|
|
@@ -347,7 +347,7 @@ export function FileUpload({
|
|
|
347
347
|
)}
|
|
348
348
|
>
|
|
349
349
|
<div className="flex-1 min-w-0">
|
|
350
|
-
<p className="text-heading-5 font-medium text-ods-text-primary truncate">
|
|
350
|
+
<p className="text-heading-5 font-medium text-ods-text-primary truncate" title={entry.fileName}>
|
|
351
351
|
{entry.fileName}
|
|
352
352
|
</p>
|
|
353
353
|
<div className="flex items-center gap-2">
|
|
@@ -385,7 +385,7 @@ export function FileUpload({
|
|
|
385
385
|
className="flex items-center gap-3 p-3 rounded-[6px] bg-ods-card border border-ods-border"
|
|
386
386
|
>
|
|
387
387
|
<div className="flex-1 min-w-0">
|
|
388
|
-
<p className="text-heading-5 font-medium text-ods-text-primary truncate">
|
|
388
|
+
<p className="text-heading-5 font-medium text-ods-text-primary truncate" title={file.name}>
|
|
389
389
|
{file.name}
|
|
390
390
|
</p>
|
|
391
391
|
<p className="text-heading-6 text-ods-text-secondary">
|
|
@@ -23,6 +23,8 @@ interface FloatingTooltipProps {
|
|
|
23
23
|
side?: "top" | "right" | "bottom" | "left"
|
|
24
24
|
className?: string
|
|
25
25
|
delayDuration?: number
|
|
26
|
+
/** Disable the tooltip without unmounting the trigger wrapper. */
|
|
27
|
+
disabled?: boolean
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
// Parse colored text markup like [YELLOW]text[/YELLOW] into JSX
|
|
@@ -75,12 +77,13 @@ function parseColoredText(text: string): React.ReactNode {
|
|
|
75
77
|
return parts.length > 0 ? <>{parts}</> : text
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
export function FloatingTooltip({
|
|
79
|
-
content,
|
|
80
|
-
children,
|
|
81
|
-
side = "right",
|
|
80
|
+
export function FloatingTooltip({
|
|
81
|
+
content,
|
|
82
|
+
children,
|
|
83
|
+
side = "right",
|
|
82
84
|
className,
|
|
83
|
-
delayDuration = 0
|
|
85
|
+
delayDuration = 0,
|
|
86
|
+
disabled = false,
|
|
84
87
|
}: FloatingTooltipProps) {
|
|
85
88
|
const [isOpen, setIsOpen] = React.useState(false)
|
|
86
89
|
const arrowRef = React.useRef<HTMLDivElement>(null)
|
|
@@ -104,6 +107,7 @@ export function FloatingTooltip({
|
|
|
104
107
|
|
|
105
108
|
const hover = useHover(context, {
|
|
106
109
|
move: false,
|
|
110
|
+
enabled: !disabled,
|
|
107
111
|
delay: { open: delayDuration, close: 0 },
|
|
108
112
|
handleClose: safePolygon(),
|
|
109
113
|
})
|
|
@@ -40,7 +40,7 @@ export const HiddenTagsPopup = forwardRef(function HiddenTagsPopup(
|
|
|
40
40
|
"border-b border-ods-border last:border-b-0",
|
|
41
41
|
)}
|
|
42
42
|
>
|
|
43
|
-
<span className="text-h5 truncate uppercase text-ods-text-primary">
|
|
43
|
+
<span className="text-h5 truncate uppercase text-ods-text-primary" title={typeof item.label === 'string' ? item.label : undefined}>
|
|
44
44
|
{item.label}
|
|
45
45
|
</span>
|
|
46
46
|
{!disabled && onRemove && (
|
|
@@ -76,6 +76,7 @@ export * from './entity-image'
|
|
|
76
76
|
export * from './feature-card'
|
|
77
77
|
export * from './feature-list'
|
|
78
78
|
export { FloatingTooltip } from './floating-tooltip'
|
|
79
|
+
export { TruncateText, type TruncateTextProps } from './truncate-text'
|
|
79
80
|
export * from './highlight-card'
|
|
80
81
|
export * from './icons-block'
|
|
81
82
|
export * from './filter-modal'
|
|
@@ -39,7 +39,7 @@ export function InfoCard({ data, className = '' }: InfoCardProps) {
|
|
|
39
39
|
>
|
|
40
40
|
{data.title && (
|
|
41
41
|
<div className="flex items-center gap-[var(--spacing-system-xsf)] self-stretch h-6">
|
|
42
|
-
<span className="text-h4 text-ods-text-primary truncate">
|
|
42
|
+
<span className="text-h4 text-ods-text-primary truncate" title={data.title}>
|
|
43
43
|
{data.title}
|
|
44
44
|
</span>
|
|
45
45
|
{data.icon}
|
|
@@ -48,7 +48,7 @@ export function InfoCard({ data, className = '' }: InfoCardProps) {
|
|
|
48
48
|
|
|
49
49
|
{/* Subtitle */}
|
|
50
50
|
{data.subtitle && (
|
|
51
|
-
<div className="text-h4 text-ods-text-secondary truncate self-stretch">
|
|
51
|
+
<div className="text-h4 text-ods-text-secondary truncate self-stretch" title={data.subtitle}>
|
|
52
52
|
{data.subtitle}
|
|
53
53
|
</div>
|
|
54
54
|
)}
|
|
@@ -66,8 +66,7 @@ export const InputTrigger = React.forwardRef<HTMLButtonElement, InputTriggerProp
|
|
|
66
66
|
className={cn(
|
|
67
67
|
"flex-1 min-w-0 text-left truncate",
|
|
68
68
|
isPlaceholder && "text-ods-text-secondary",
|
|
69
|
-
)}
|
|
70
|
-
>
|
|
69
|
+
)} title={isPlaceholder ? placeholder : (typeof selectedLabel === 'string' ? selectedLabel : undefined)}>
|
|
71
70
|
{isPlaceholder ? placeholder : selectedLabel}
|
|
72
71
|
</span>
|
|
73
72
|
{endIcon && (
|
|
@@ -104,10 +104,10 @@ export function OrganizationCard({
|
|
|
104
104
|
/>
|
|
105
105
|
|
|
106
106
|
<div className="flex-1 flex flex-col justify-center py-2 min-w-0">
|
|
107
|
-
<h3 className="font-['DM_Sans'] font-bold text-lg leading-[1.33] tracking-[-0.02em] text-ods-text-primary transition-colors truncate">
|
|
107
|
+
<h3 className="font-['DM_Sans'] font-bold text-lg leading-[1.33] tracking-[-0.02em] text-ods-text-primary transition-colors truncate" title={organization.name}>
|
|
108
108
|
{organization.name}
|
|
109
109
|
</h3>
|
|
110
|
-
<p className="font-['DM_Sans'] font-medium text-sm leading-[1.43] text-ods-text-secondary truncate">
|
|
110
|
+
<p className="font-['DM_Sans'] font-medium text-sm leading-[1.43] text-ods-text-secondary truncate" title={organization.industry || organization.tier || organization.websiteUrl || "Organization"}>
|
|
111
111
|
{organization.industry || organization.tier || organization.websiteUrl || "Organization"}
|
|
112
112
|
</p>
|
|
113
113
|
</div>
|
|
@@ -116,7 +116,7 @@ export function OrganizationCard({
|
|
|
116
116
|
{/* Description */}
|
|
117
117
|
{organization.description && (
|
|
118
118
|
<div className="w-full h-12 overflow-hidden">
|
|
119
|
-
<p className="font-['DM_Sans'] font-medium text-lg leading-[1.33] text-ods-text-primary line-clamp-2">
|
|
119
|
+
<p className="font-['DM_Sans'] font-medium text-lg leading-[1.33] text-ods-text-primary line-clamp-2" title={organization.description}>
|
|
120
120
|
{organization.description}
|
|
121
121
|
</p>
|
|
122
122
|
</div>
|
|
@@ -145,8 +145,7 @@ const RadioGroupBlock = React.forwardRef<
|
|
|
145
145
|
className={cn(
|
|
146
146
|
"font-[family-name:var(--font-h4-family)] font-[number:var(--font-h4-weight)] text-[length:var(--font-size-h4-body)] leading-[24px]",
|
|
147
147
|
"text-ods-text-primary select-none truncate"
|
|
148
|
-
)}
|
|
149
|
-
>
|
|
148
|
+
)} title={typeof option.label === 'string' ? option.label : undefined}>
|
|
150
149
|
{option.label}
|
|
151
150
|
</span>
|
|
152
151
|
{option.description && (
|
|
@@ -168,7 +167,7 @@ const RadioGroupBlock = React.forwardRef<
|
|
|
168
167
|
})}
|
|
169
168
|
</RadioGroupPrimitive.Root>
|
|
170
169
|
{error && (
|
|
171
|
-
<p className="absolute bottom-0 left-0 right-0 translate-y-full text-h6 truncate text-ods-error">
|
|
170
|
+
<p className="absolute bottom-0 left-0 right-0 translate-y-full text-h6 truncate text-ods-error" title={error}>
|
|
172
171
|
{error}
|
|
173
172
|
</p>
|
|
174
173
|
)}
|
|
@@ -325,11 +325,11 @@ export function SearchInput({
|
|
|
325
325
|
<div className={cn(
|
|
326
326
|
"text-sm font-medium leading-5 truncate",
|
|
327
327
|
isHighlighted ? "text-ods-accent" : "text-ods-text-primary"
|
|
328
|
-
)}>
|
|
328
|
+
)} title={result.title}>
|
|
329
329
|
{result.title}
|
|
330
330
|
</div>
|
|
331
331
|
{result.description && (
|
|
332
|
-
<div className="text-xs leading-4 text-ods-text-secondary truncate mt-0.5">
|
|
332
|
+
<div className="text-xs leading-4 text-ods-text-secondary truncate mt-0.5" title={result.description}>
|
|
333
333
|
{result.description}
|
|
334
334
|
</div>
|
|
335
335
|
)}
|
|
@@ -61,9 +61,9 @@ export function ServiceCard({ title, subtitle, icon, tag, rows, className }: Ser
|
|
|
61
61
|
{resolvedIcon}
|
|
62
62
|
</div>
|
|
63
63
|
<div className="min-w-0">
|
|
64
|
-
<div className="text-xl font-semibold text-ods-text-primary truncate">{title}</div>
|
|
64
|
+
<div className="text-xl font-semibold text-ods-text-primary truncate" title={title}>{title}</div>
|
|
65
65
|
{subtitle && (
|
|
66
|
-
<div className="text-sm text-ods-text-secondary truncate">{subtitle}</div>
|
|
66
|
+
<div className="text-sm text-ods-text-secondary truncate" title={subtitle}>{subtitle}</div>
|
|
67
67
|
)}
|
|
68
68
|
</div>
|
|
69
69
|
</div>
|
|
@@ -104,7 +104,7 @@ function ServiceCardRowItem({ row }: { row: ServiceCardRow }) {
|
|
|
104
104
|
<div className="w-20 md:w-24 shrink-0 text-sm font-medium text-ods-text-primary">{row.label}</div>
|
|
105
105
|
)}
|
|
106
106
|
<div className={cn('flex-1 h-12 rounded-md border border-ods-border bg-ods-bg px-3 md:px-4 flex items-center justify-between min-w-0', row.monospace ? 'font-mono' : '')}>
|
|
107
|
-
<div className="truncate text-ods-text-primary min-w-0">{displayValue}</div>
|
|
107
|
+
<div className="truncate text-ods-text-primary min-w-0" title={typeof row.value === 'string' ? row.value : undefined}>{displayValue}</div>
|
|
108
108
|
<div className="flex items-center gap-2 pl-3 flex-shrink-0">
|
|
109
109
|
{actions.reveal && (
|
|
110
110
|
<button
|