@smicolon/fasla-ui 0.4.1 → 0.4.2

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.cjs CHANGED
@@ -5,8 +5,11 @@ var tailwindMerge = require('tailwind-merge');
5
5
  var framerMotion = require('framer-motion');
6
6
 
7
7
  // src/lib/utils.ts
8
+ var twMerge = tailwindMerge.extendTailwindMerge({
9
+ extend: { classGroups: { "font-size": [{ text: ["xxs", "link", "list-header"] }] } }
10
+ });
8
11
  function cn(...inputs) {
9
- return tailwindMerge.twMerge(clsx.clsx(inputs));
12
+ return twMerge(clsx.clsx(inputs));
10
13
  }
11
14
 
12
15
  // src/tokens/model.ts
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
3
  import { useReducedMotion } from 'framer-motion';
4
4
 
5
5
  // src/lib/utils.ts
6
+ var twMerge = extendTailwindMerge({
7
+ extend: { classGroups: { "font-size": [{ text: ["xxs", "link", "list-header"] }] } }
8
+ });
6
9
  function cn(...inputs) {
7
10
  return twMerge(clsx(inputs));
8
11
  }
@@ -4,8 +4,11 @@ var clsx = require('clsx');
4
4
  var tailwindMerge = require('tailwind-merge');
5
5
 
6
6
  // src/lib/utils.ts
7
+ var twMerge = tailwindMerge.extendTailwindMerge({
8
+ extend: { classGroups: { "font-size": [{ text: ["xxs", "link", "list-header"] }] } }
9
+ });
7
10
  function cn(...inputs) {
8
- return tailwindMerge.twMerge(clsx.clsx(inputs));
11
+ return twMerge(clsx.clsx(inputs));
9
12
  }
10
13
 
11
14
  exports.cn = cn;
package/dist/lib/utils.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
3
 
4
4
  // src/lib/utils.ts
5
+ var twMerge = extendTailwindMerge({
6
+ extend: { classGroups: { "font-size": [{ text: ["xxs", "link", "list-header"] }] } }
7
+ });
5
8
  function cn(...inputs) {
6
9
  return twMerge(clsx(inputs));
7
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smicolon/fasla-ui",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Professional UI components with animations and app building blocks",
5
5
  "license": "MIT",
6
6
  "author": "Smicolon",
@@ -0,0 +1,38 @@
1
+ import * as React from "react"
2
+ import { describe, it, expect, vi } from "vitest"
3
+ import { render } from "@testing-library/react"
4
+
5
+ // shadcn's cn, which a project set up with `shadcn init` keeps: plain
6
+ // tailwind-merge, which doesn't know Fasla's `text-xxs`.
7
+ vi.mock("../../../src/lib/utils", async () => {
8
+ const { clsx } = await import("clsx")
9
+ const { twMerge } = await import("tailwind-merge")
10
+ return { cn: (...inputs: Parameters<typeof clsx>) => twMerge(clsx(inputs)) }
11
+ })
12
+
13
+ import { Avatar, avatarVariants } from "./avatar"
14
+
15
+ const sizes = ["32", "24", "12"] as const
16
+ const radii = ["standard", "rounded"] as const
17
+
18
+ function frameOf(props: React.ComponentProps<typeof Avatar>) {
19
+ const { container } = render(<Avatar data-testid="avatar" {...props} />)
20
+ return container.querySelector("[data-testid='avatar']")!.firstElementChild as HTMLElement
21
+ }
22
+
23
+ describe("Avatar with shadcn's cn", () => {
24
+ it.each(sizes)("keeps text-foreground at %s, where the initials and icon take it", (size) => {
25
+ expect(frameOf({ size, variant: "initials", name: "Layla" })).toHaveClass("text-foreground")
26
+ expect(frameOf({ size, variant: "icon" })).toHaveClass("text-foreground")
27
+ })
28
+
29
+ // Every class, in order, exactly as the variants give them: nothing merged
30
+ // away, nothing added, so Avatar looks as it did at every size.
31
+ it.each(sizes.flatMap((size) => radii.flatMap((radius) => [true, false].map((border) => [size, radius, border] as const))))(
32
+ "draws %s %s border=%s with the variants' classes and bg-muted, unmerged",
33
+ (size, radius, border) => {
34
+ const frame = frameOf({ size, radius, border, variant: "initials", name: "Layla" })
35
+ expect(frame.className).toBe(`${avatarVariants({ size, radius, border })} bg-muted`)
36
+ }
37
+ )
38
+ })
@@ -31,10 +31,12 @@ describe("Avatar", () => {
31
31
  ["24", "size-6", "rounded-[var(--radius-md)]", "text-xs"],
32
32
  // Figma's XXS: 10px, leaded 14 in English and 16 in Arabic.
33
33
  ["12", "size-3", "rounded-[var(--radius-xs)]", "text-xxs"],
34
- ] as const)("Standard %s is %s, %s, %s", (size, box, corner, text) => {
34
+ ] as const)("Standard %s is %s, %s, %s, in the foreground colour", (size, box, corner, text) => {
35
35
  const { root, frame } = avatar({ size, name: "Layla" })
36
36
  expect(root).toHaveClass(box)
37
- expect(frame).toHaveClass(corner, text)
37
+ // text-foreground too: merged beside an unknown size, cn dropped it at
38
+ // 12 and the initials took the colour of whatever held them.
39
+ expect(frame).toHaveClass(corner, text, "text-foreground")
38
40
  })
39
41
 
40
42
  it.each(["32", "24", "12"] as const)("Rounded %s is a circle", (size) => {
@@ -207,11 +207,16 @@ const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
207
207
  {...props}
208
208
  >
209
209
  <span
210
- className={cn(
210
+ // Joined, not cn(): every class here is Avatar's own and none
211
+ // conflicts. A project's cn may not know `text-xxs` — shadcn's
212
+ // doesn't — and takes it for a colour, dropping `text-foreground`.
213
+ className={[
211
214
  avatarVariants({ size, radius, border }),
212
215
  // Figma's Image variants have no fill; the fallback sits on `muted`.
213
- !loaded && "bg-muted"
214
- )}
216
+ !loaded && "bg-muted",
217
+ ]
218
+ .filter(Boolean)
219
+ .join(" ")}
215
220
  >
216
221
  {!loaded &&
217
222
  (letters ? (