Skip to content

Commit

Permalink
Icon block supports color
Browse files Browse the repository at this point in the history
  • Loading branch information
dabbott committed Mar 2, 2023
1 parent 3a569a7 commit ef8fd34
Show file tree
Hide file tree
Showing 6 changed files with 586 additions and 40 deletions.
225 changes: 225 additions & 0 deletions packages/site/safelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,231 @@ bg-rose-600
bg-rose-700
bg-rose-800
bg-rose-900
fill-inherit
fill-current
fill-transparent
fill-black
fill-white
fill-slate-50
fill-slate-100
fill-slate-200
fill-slate-300
fill-slate-400
fill-slate-500
fill-slate-600
fill-slate-700
fill-slate-800
fill-slate-900
fill-gray-50
fill-gray-100
fill-gray-200
fill-gray-300
fill-gray-400
fill-gray-500
fill-gray-600
fill-gray-700
fill-gray-800
fill-gray-900
fill-zinc-50
fill-zinc-100
fill-zinc-200
fill-zinc-300
fill-zinc-400
fill-zinc-500
fill-zinc-600
fill-zinc-700
fill-zinc-800
fill-zinc-900
fill-neutral-50
fill-neutral-100
fill-neutral-200
fill-neutral-300
fill-neutral-400
fill-neutral-500
fill-neutral-600
fill-neutral-700
fill-neutral-800
fill-neutral-900
fill-stone-50
fill-stone-100
fill-stone-200
fill-stone-300
fill-stone-400
fill-stone-500
fill-stone-600
fill-stone-700
fill-stone-800
fill-stone-900
fill-red-50
fill-red-100
fill-red-200
fill-red-300
fill-red-400
fill-red-500
fill-red-600
fill-red-700
fill-red-800
fill-red-900
fill-orange-50
fill-orange-100
fill-orange-200
fill-orange-300
fill-orange-400
fill-orange-500
fill-orange-600
fill-orange-700
fill-orange-800
fill-orange-900
fill-amber-50
fill-amber-100
fill-amber-200
fill-amber-300
fill-amber-400
fill-amber-500
fill-amber-600
fill-amber-700
fill-amber-800
fill-amber-900
fill-yellow-50
fill-yellow-100
fill-yellow-200
fill-yellow-300
fill-yellow-400
fill-yellow-500
fill-yellow-600
fill-yellow-700
fill-yellow-800
fill-yellow-900
fill-lime-50
fill-lime-100
fill-lime-200
fill-lime-300
fill-lime-400
fill-lime-500
fill-lime-600
fill-lime-700
fill-lime-800
fill-lime-900
fill-green-50
fill-green-100
fill-green-200
fill-green-300
fill-green-400
fill-green-500
fill-green-600
fill-green-700
fill-green-800
fill-green-900
fill-emerald-50
fill-emerald-100
fill-emerald-200
fill-emerald-300
fill-emerald-400
fill-emerald-500
fill-emerald-600
fill-emerald-700
fill-emerald-800
fill-emerald-900
fill-teal-50
fill-teal-100
fill-teal-200
fill-teal-300
fill-teal-400
fill-teal-500
fill-teal-600
fill-teal-700
fill-teal-800
fill-teal-900
fill-cyan-50
fill-cyan-100
fill-cyan-200
fill-cyan-300
fill-cyan-400
fill-cyan-500
fill-cyan-600
fill-cyan-700
fill-cyan-800
fill-cyan-900
fill-sky-50
fill-sky-100
fill-sky-200
fill-sky-300
fill-sky-400
fill-sky-500
fill-sky-600
fill-sky-700
fill-sky-800
fill-sky-900
fill-blue-50
fill-blue-100
fill-blue-200
fill-blue-300
fill-blue-400
fill-blue-500
fill-blue-600
fill-blue-700
fill-blue-800
fill-blue-900
fill-indigo-50
fill-indigo-100
fill-indigo-200
fill-indigo-300
fill-indigo-400
fill-indigo-500
fill-indigo-600
fill-indigo-700
fill-indigo-800
fill-indigo-900
fill-violet-50
fill-violet-100
fill-violet-200
fill-violet-300
fill-violet-400
fill-violet-500
fill-violet-600
fill-violet-700
fill-violet-800
fill-violet-900
fill-purple-50
fill-purple-100
fill-purple-200
fill-purple-300
fill-purple-400
fill-purple-500
fill-purple-600
fill-purple-700
fill-purple-800
fill-purple-900
fill-fuchsia-50
fill-fuchsia-100
fill-fuchsia-200
fill-fuchsia-300
fill-fuchsia-400
fill-fuchsia-500
fill-fuchsia-600
fill-fuchsia-700
fill-fuchsia-800
fill-fuchsia-900
fill-pink-50
fill-pink-100
fill-pink-200
fill-pink-300
fill-pink-400
fill-pink-500
fill-pink-600
fill-pink-700
fill-pink-800
fill-pink-900
fill-rose-50
fill-rose-100
fill-rose-200
fill-rose-300
fill-rose-400
fill-rose-500
fill-rose-600
fill-rose-700
fill-rose-800
fill-rose-900
blur-0
blur-none
blur-sm
Expand Down
44 changes: 32 additions & 12 deletions packages/site/src/ayon/blocks/IconBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Image } from '@chakra-ui/react';
import { BlockDefinition } from 'noya-state';
import React from 'react';
import { parseBlock } from '../parse';
import { isApproximatelySquare, isWithinRectRange } from './score';
import { iconSymbol } from './symbols';
import { getTailwindClassesByGroup, isTailwindClassGroup } from './tailwind';
import { resolveColor } from './tailwindColors';

export const IconBlock: BlockDefinition = {
symbol: iconSymbol,
parser: 'regular',
usesResolver: true,
hashtags: getTailwindClassesByGroup('fill'),
infer: ({ frame, blockText }) =>
isWithinRectRange({
rect: frame,
Expand All @@ -18,16 +22,32 @@ export const IconBlock: BlockDefinition = {
}) && isApproximatelySquare(frame, 0.2)
? 0.85
: 0,
render: (props) => (
<Image
src={
props.resolvedBlockData?.resolvedText ??
'https://api.iconify.design/material-symbols/menu.svg'
}
fit="contain"
align="middle"
w="100%"
h="100%"
/>
),
render: (props) => {
const src =
props.resolvedBlockData?.resolvedText ??
'https://api.iconify.design/material-symbols/menu.svg';
const { parameters } = parseBlock(props.blockText, 'regular');
const hashtags = Object.keys(parameters);
const fillClassName = hashtags
.slice()
.reverse()
.find((hashtag) => isTailwindClassGroup(hashtag, 'fill'));
const fill = fillClassName ? resolveColor(fillClassName) : undefined;

if (fill) {
return (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: fill,
maskImage: `url(${src}) center / contain no-repeat`,
WebkitMask: `url(${src}) center / contain no-repeat`,
}}
/>
);
} else {
return <Image src={src} fit="contain" align="middle" w="100%" h="100%" />;
}
},
};
51 changes: 24 additions & 27 deletions packages/site/src/ayon/blocks/tailwind.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,23 @@
import { groupBy, memoize, partition } from 'noya-utils';
import { SafelistConfig } from 'tailwindcss/types/config';
import { groupBy, memoize } from 'noya-utils';

const allClassNames = (
require('../../../safelist.txt').default as string
).split('\n');

const allClassNamesSet = new Set(allClassNames);

type SafelistPattern = SafelistConfig[0];

function isSafe(className: string, item?: SafelistPattern) {
return !item
? false
: typeof item === 'string'
? className === item
: item.pattern.test(className);
}

export function getTailwindClasses(filters?: SafelistConfig[0][]) {
if (!filters) return allClassNames;

return allClassNames.filter((className) =>
filters.some((filter) => isSafe(className, filter)),
);
}

export function isSupportedTailwindClass(className: string) {
return allClassNamesSet.has(className);
}

const isTextClassRE = /^(text|font|truncate|leading)/;
const isFillClassRE = /^fill-/;

export const [tailwindTextClasses, tailwindBlockClasses] = partition(
allClassNames,
(item) => isTextClassRE.test(item),
export const tailwindTextClasses = allClassNames.filter((item) =>
isTextClassRE.test(item),
);
export const tailwindBlockClasses = allClassNames.filter(
(item) => !isTextClassRE.test(item) && !isFillClassRE.test(item),
);

export function getBlockClassName(hashtags: string[]) {
Expand All @@ -55,6 +39,7 @@ export const classGroups = {
// From https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js
textColor:
/^text-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)/,
fill: /^fill-/,
justify: /^justify/,
items: /^items/,
gap: /^gap-/,
Expand All @@ -80,18 +65,30 @@ export const classGroups = {
none: /.*/,
};

type ClassGroup = keyof typeof classGroups;
type ClassGroupKey = keyof typeof classGroups;

export function hasClassGroup(group: ClassGroup, hashtags: string[]) {
export function hasClassGroup(group: ClassGroupKey, hashtags: string[]) {
return hashtags.some((className) => classGroups[group].test(className));
}

export const getTailwindClassGroup = memoize(
(className: string): ClassGroup => {
(className: string): ClassGroupKey => {
const entry = Object.entries(classGroups).find(([, re]) =>
re.test(className),
)!;

return entry[0] as ClassGroup;
return entry[0] as ClassGroupKey;
},
);

export const isTailwindClassGroup = memoize(
(className: string, group: ClassGroupKey): boolean => {
return classGroups[group].test(className);
},
);

export const getTailwindClassesByGroup = memoize((group: ClassGroupKey) => {
return allClassNames.filter((className) =>
classGroups[group].test(className),
);
});
Loading

0 comments on commit ef8fd34

Please sign in to comment.