@adatechnology/conversations-ui 0.6.0 → 0.6.1

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/index.js CHANGED
@@ -3,11 +3,6 @@ import {
3
3
  TooltipLayer,
4
4
  WhatsAppMessagePreview
5
5
  } from "./chunk-HOKNKXIT.js";
6
- import {
7
- CHAT_TEXT_PRIMARY_CLASS,
8
- CHAT_TEXT_SECONDARY_CLASS,
9
- MessageText
10
- } from "./chunk-OVFCLRQQ.js";
11
6
  import {
12
7
  AudioPlayer,
13
8
  AudioRecorderButton,
@@ -70,6 +65,11 @@ import {
70
65
  useDarkMode,
71
66
  useIsDarkTheme
72
67
  } from "./chunk-MRVFFJEH.js";
68
+ import {
69
+ CHAT_TEXT_PRIMARY_CLASS,
70
+ CHAT_TEXT_SECONDARY_CLASS,
71
+ MessageText
72
+ } from "./chunk-OVFCLRQQ.js";
73
73
  import {
74
74
  CHANNEL_CAPABILITIES,
75
75
  CHANNEL_FILTER_ALL,
package/dist/styles.css CHANGED
@@ -1928,6 +1928,14 @@
1928
1928
  transition: background-color 0.12s, border-color 0.12s;
1929
1929
  }
1930
1930
  }
1931
+ .cv-p-filters,
1932
+ .cv-p-quick,
1933
+ .cv-p-search,
1934
+ .cv-p-composer,
1935
+ .cv-p-thread__header,
1936
+ .cv-p-thread__subject-card {
1937
+ flex: 0 0 auto;
1938
+ }
1931
1939
  .cv-p-root {
1932
1940
  display: flex;
1933
1941
  flex-direction: column;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/conversations-ui",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "WhatsApp conversation UI components — parametrizável por endpoint, tema e feature flags",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -35,8 +35,8 @@
35
35
  "clsx": "^2.1.1",
36
36
  "lucide-react": "^1.21.0",
37
37
  "tailwind-merge": "^3.6.0",
38
- "@adatechnology/conversation-contracts": "0.5.0",
39
- "@adatechnology/meta-whatsapp-contracts": "0.6.0"
38
+ "@adatechnology/meta-whatsapp-contracts": "0.6.0",
39
+ "@adatechnology/conversation-contracts": "0.5.0"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@xyflow/react": "^12",
@@ -0,0 +1,31 @@
1
+ export type CssBlock = { readonly prelude: string; readonly body: string | undefined }
2
+
3
+ export function splitBlocks(css: string): CssBlock[] {
4
+ const blocks: CssBlock[] = []
5
+ let depth = 0
6
+ let start = 0
7
+ let bodyStart = 0
8
+ let prelude = ''
9
+ for (let index = 0; index < css.length; index += 1) {
10
+ const char = css[index]
11
+ if (depth === 0 && char === ';') {
12
+ blocks.push({ prelude: css.slice(start, index).trim(), body: undefined })
13
+ start = index + 1
14
+ }
15
+ if (char === '{') {
16
+ if (depth === 0) {
17
+ prelude = css.slice(start, index).trim()
18
+ bodyStart = index + 1
19
+ }
20
+ depth += 1
21
+ }
22
+ if (char === '}') {
23
+ depth -= 1
24
+ if (depth === 0) {
25
+ blocks.push({ prelude, body: css.slice(bodyStart, index) })
26
+ start = index + 1
27
+ }
28
+ }
29
+ }
30
+ return blocks
31
+ }
@@ -2,6 +2,8 @@ import { readFileSync } from 'node:fs'
2
2
  import { join } from 'node:path'
3
3
  import { describe, expect, it } from 'bun:test'
4
4
 
5
+ import { splitBlocks } from './cssBlocks.test-helper'
6
+
5
7
  // legacyStyles.fixture.css is the styles.css shipped by 0.4.2; the stylesheet is global, so anything
6
8
  // added since must be namespaced under .cv- and must not reach the host's own elements.
7
9
  const LEGACY_CSS = readFileSync(join(import.meta.dir, 'legacyStyles.fixture.css'), 'utf8')
@@ -10,39 +12,8 @@ const CURRENT_CSS = readFileSync(join(import.meta.dir, 'styles.css'), 'utf8')
10
12
  const NESTED_AT_RULES = ['@media', '@supports']
11
13
  const ALLOWED_NEW_AT_RULES = ['@media', '@supports', '@keyframes']
12
14
 
13
- type Block = { readonly prelude: string; readonly body: string | undefined }
14
15
  type Inventory = { selectors: string[]; atRules: string[]; keyframeNames: string[] }
15
16
 
16
- function splitBlocks(css: string): Block[] {
17
- const blocks: Block[] = []
18
- let depth = 0
19
- let start = 0
20
- let bodyStart = 0
21
- let prelude = ''
22
- for (let index = 0; index < css.length; index += 1) {
23
- const char = css[index]
24
- if (depth === 0 && char === ';') {
25
- blocks.push({ prelude: css.slice(start, index).trim(), body: undefined })
26
- start = index + 1
27
- }
28
- if (char === '{') {
29
- if (depth === 0) {
30
- prelude = css.slice(start, index).trim()
31
- bodyStart = index + 1
32
- }
33
- depth += 1
34
- }
35
- if (char === '}') {
36
- depth -= 1
37
- if (depth === 0) {
38
- blocks.push({ prelude, body: css.slice(bodyStart, index) })
39
- start = index + 1
40
- }
41
- }
42
- }
43
- return blocks
44
- }
45
-
46
17
  function splitSelectorList(prelude: string): string[] {
47
18
  const parts: string[] = []
48
19
  let parenthesisDepth = 0
@@ -0,0 +1,82 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+ import { describe, expect, it } from 'bun:test'
4
+
5
+ import { splitBlocks } from './cssBlocks.test-helper'
6
+
7
+ const CSS = readFileSync(join(import.meta.dir, 'styles.css'), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '')
8
+
9
+ const NON_SHRINKING_ITEMS = [
10
+ '.cv-p-filters',
11
+ '.cv-p-quick',
12
+ '.cv-p-search',
13
+ '.cv-p-composer',
14
+ '.cv-p-thread__header',
15
+ '.cv-p-thread__subject-card',
16
+ ]
17
+
18
+ type FlexState = { grow: number; shrink: number }
19
+
20
+ const FLEX_KEYWORDS: Record<string, FlexState> = {
21
+ none: { grow: 0, shrink: 0 },
22
+ auto: { grow: 1, shrink: 1 },
23
+ initial: { grow: 0, shrink: 1 },
24
+ }
25
+
26
+ function parseFlexShorthand(value: string): FlexState {
27
+ const keyword = FLEX_KEYWORDS[value]
28
+ if (keyword) return { ...keyword }
29
+ const numbers = value
30
+ .split(/\s+/)
31
+ .filter((token) => /^\d*\.?\d+$/.test(token))
32
+ .map(Number)
33
+ return { grow: numbers[0] ?? 0, shrink: numbers[1] ?? 1 }
34
+ }
35
+
36
+ function cleanValue(raw: string): string {
37
+ return raw
38
+ .replace(/!important/g, '')
39
+ .trim()
40
+ .toLowerCase()
41
+ }
42
+
43
+ // Only depth-0 style rules count (@media/@supports are conditional); later declarations win.
44
+ function effectiveFlex(selector: string): FlexState | undefined {
45
+ let state: FlexState | undefined
46
+ for (const { prelude, body } of splitBlocks(CSS)) {
47
+ if (body === undefined || prelude.startsWith('@')) continue
48
+ if (!prelude.split(',').some((entry) => entry.trim() === selector)) continue
49
+ for (const declaration of body.split(';')) {
50
+ const separator = declaration.indexOf(':')
51
+ if (separator === -1) continue
52
+ const property = declaration.slice(0, separator).trim().toLowerCase()
53
+ const value = cleanValue(declaration.slice(separator + 1))
54
+ if (property === 'flex') state = parseFlexShorthand(value)
55
+ if (property === 'flex-shrink') state = { grow: state?.grow ?? 0, shrink: Number(value) }
56
+ }
57
+ }
58
+ return state
59
+ }
60
+
61
+ function hasMinHeightZero(selector: string): boolean {
62
+ return splitBlocks(CSS).some(
63
+ ({ prelude, body }) =>
64
+ body !== undefined &&
65
+ !prelude.startsWith('@') &&
66
+ prelude.split(',').some((entry) => entry.trim() === selector) &&
67
+ /min-height:\s*0\b/.test(body),
68
+ )
69
+ }
70
+
71
+ describe('participant view flex layout', () => {
72
+ it.each(NON_SHRINKING_ITEMS)('%s does not shrink inside a flex column', (selector) => {
73
+ expect(effectiveFlex(selector)?.shrink).toBe(0)
74
+ })
75
+
76
+ it('keeps the thread scroller as the only shrinking, growing region', () => {
77
+ const scroller = effectiveFlex('.cv-p-thread__scroll')
78
+ expect(scroller?.grow).toBe(1)
79
+ expect(scroller?.shrink).toBe(1)
80
+ expect(hasMinHeightZero('.cv-p-thread__scroll')).toBe(true)
81
+ })
82
+ })
package/src/styles.css CHANGED
@@ -1295,5 +1295,8 @@
1295
1295
  .cv-p-row, .cv-p-button, .cv-p-chip { transition: background-color 0.12s, border-color 0.12s; }
1296
1296
  }
1297
1297
 
1298
+ /* Item de coluna flex com overflow ≠ visible (no próprio item) perde o min-height:auto e encolhe; os quatro últimos são defensivos. */
1299
+ .cv-p-filters, .cv-p-quick, .cv-p-search, .cv-p-composer, .cv-p-thread__header, .cv-p-thread__subject-card { flex: 0 0 auto; }
1300
+
1298
1301
  .cv-p-root { display: flex; flex-direction: column; min-height: 0; height: 100%; }
1299
1302
  .cv-p-root__screen { display: flex; flex-direction: column; flex: 1; min-height: 0; }