This commit is contained in:
Paweł Kuna 2025-12-25 20:21:01 +00:00 committed by GitHub
commit ff9de2941a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 9058 additions and 11 deletions

View File

@ -49,8 +49,7 @@ jobs:
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 8
run_install: false
version: 10.26.1
- name: Get pnpm store directory
shell: bash

View File

@ -33,7 +33,7 @@
"validate": "node ./.build/validate-icons.mjs",
"release": "git pull && release-it --verbose",
"build:copy": "rm -rf ./icons && mkdir ./icons && cp ./_site/tags.json tags.json && cp ./_site/icons/* ./icons/ && rm -rf ./_site/",
"build:packages": "pnpm run build:icons && pnpm run build:sprite && pnpm run build:react && pnpm run build:react-native && pnpm run build:preact && pnpm run build:solidjs && pnpm run build:svelte && pnpm run build:svelte-runes && pnpm run build:vue && pnpm run build:png && pnpm run build:pdf && pnpm run build:esp && pnpm run build:webfont",
"build:packages": "pnpm run build:icons && pnpm run build:sprite && pnpm run build:react && pnpm run build:react-native && pnpm run build:preact && pnpm run build:solidjs && pnpm run build:svelte && pnpm run build:svelte-runes && pnpm run build:vue && pnpm run build:astro && pnpm run build:png && pnpm run build:pdf && pnpm run build:esp && pnpm run build:webfont",
"build:icons": "pnpm --filter @tabler/icons build",
"build:react": "pnpm --filter @tabler/icons-react build",
"build:react-native": "pnpm --filter @tabler/icons-react-native build",
@ -42,6 +42,7 @@
"build:svelte": "pnpm --filter @tabler/icons-svelte build",
"build:svelte-runes": "pnpm --filter @tabler/icons-svelte-runes build",
"build:vue": "pnpm --filter @tabler/icons-vue build",
"build:astro": "pnpm --filter @tabler/icons-astro build",
"build:png": "pnpm --filter @tabler/icons-png build",
"build:pdf": "pnpm --filter @tabler/icons-pdf build",
"build:esp": "pnpm --filter @tabler/icons-esp build",
@ -114,7 +115,6 @@
"release": true
}
},
"packageManager": "pnpm@10.26.1",
"pnpm": {
"ignoredBuiltDependencies": [
"@parcel/watcher",

View File

@ -0,0 +1,28 @@
# @tabler/icons-astro
A set of free MIT-licensed high-quality SVG icons for you to use in your Astro projects.
## Installation
```bash
npm install @tabler/icons-astro
# or
yarn add @tabler/icons-astro
# or
pnpm add @tabler/icons-astro
```
## Usage
```astro
---
import { IconHome } from '@tabler/icons-astro/icons';
---
<IconHome size={24} color="currentColor" />
```
## License
MIT

View File

@ -0,0 +1,53 @@
#!/usr/bin/env node
import { buildJsIcons, buildIconsList } from '../../.build/build-icons.mjs'
const componentTemplate = ({
type,
name,
namePascal,
children
}) => {
// Remove key from children (Astro doesn't need keyed children in loops)
const keylessChildren = children.map((c) => {
const [element, attrs] = c;
const { key, ...otherAttrs } = attrs;
return [element, otherAttrs];
});
return `import createTablerIcon from '../createTablerIcon';
import type { AstroComponent } from '../types';
/**
* @component @name Icon${namePascal}
* @description Tabler SVG icon component, renders SVG Element with children.
*
* @param {import('../types').IconProps} props - Tabler icons props and any valid SVG attribute
* @returns {any} Astro Component
*/
const Icon${namePascal} = createTablerIcon('${name}', ${JSON.stringify(keylessChildren)}, '${type}') as AstroComponent;
export default Icon${namePascal};
`;
};
const aliasTemplate = ({ fromPascal, to }) => `export { default as Icon${fromPascal} } from './icons/${to}.ts';\n`
const indexItemTemplate = ({
name,
namePascal
}) => `export { default as Icon${namePascal} } from './${name}.ts';`
buildJsIcons({
name: 'icons-astro',
componentTemplate,
indexItemTemplate,
aliasTemplate,
extension: 'ts',
key: false,
indexFile: 'index.ts',
pascalName: false,
})
buildIconsList('icons-astro')

View File

@ -0,0 +1,56 @@
{
"name": "@tabler/icons-astro",
"version": "3.36.0",
"license": "MIT",
"author": "codecalm",
"description": "A set of free MIT-licensed high-quality SVG icons for you to use in your web projects.",
"homepage": "https://tabler-icons.io",
"bugs": {
"url": "https://github.com/tabler/tabler-icons/issues"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/codecalm"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tabler/tabler-icons.git",
"directory": "packages/icons-astro"
},
"type": "module",
"exports": {
".": {
"import": "./src/tabler-icons-astro.ts"
},
"./icons": {
"import": "./src/icons/index.ts"
},
"./icons/*": {
"import": "./src/icons/*.ts"
}
},
"sideEffects": false,
"files": [
"src",
"LICENSE",
"README.md"
],
"scripts": {
"build": "pnpm run clean && pnpm run copy:license && pnpm run build:icons",
"build:icons": "node build.mjs",
"copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && find . ! -name '.gitkeep' -path '*/src/icons/*' -delete",
"test": "echo \"No tests yet\"",
"imports-check": "attw $(npm pack)"
},
"dependencies": {
"@tabler/icons": "3.36.0"
},
"devDependencies": {
"@astrojs/ts-plugin": "^1.10.6",
"astro": "^5.16.6"
},
"peerDependencies": {
"astro": "^4 || ^5"
}
}

View File

@ -0,0 +1,39 @@
---
import defaultAttributes from './defaultAttributes';
import type { IconProps as Props, IconNodeChild } from './types';
const {
type = 'outline',
color = 'currentColor',
size = 24,
'stroke-width': strokeWidth = 2,
stroke,
iconNode = [],
class: className,
...rest
} = Astro.props;
const typeAttrs = type === 'filled'
? { fill: color }
: {
'stroke-width': stroke || strokeWidth,
stroke: color,
};
const svgAttrs = {
...defaultAttributes[type as 'outline' | 'filled'],
width: size,
height: size,
...typeAttrs,
...rest,
};
---
<svg
{...svgAttrs}
class:list={['tabler-icon', className]}
>
{iconNode.map(([Tag, attrs]: IconNodeChild) => <Tag {...attrs} />)}
<slot />
</svg>

View File

@ -0,0 +1,57 @@
export { default as Icon123 } from './icons/number-123.ts';
export { default as Icon360 } from './icons/view-360-arrow.ts';
export { default as IconCodeAsterix } from './icons/code-asterisk.ts';
export { default as IconDiscount2 } from './icons/rosette-discount.ts';
export { default as IconDiscount2Off } from './icons/rosette-discount-off.ts';
export { default as IconDiscountCheck } from './icons/rosette-discount-check.ts';
export { default as IconHandRock } from './icons/hand-love-you.ts';
export { default as IconSortDeacendingSmallBig } from './icons/sort-descending-small-big.ts';
export { default as IconShiJumping } from './icons/ski-jumping.ts';
export { default as IconBoxSeam } from './icons/package.ts';
export { default as IconKering } from './icons/kerning.ts';
export { default as Icon2fa } from './icons/auth-2fa.ts';
export { default as Icon3dCubeSphere } from './icons/cube-3d-sphere.ts';
export { default as Icon3dCubeSphereOff } from './icons/cube-3d-sphere-off.ts';
export { default as Icon3dRotate } from './icons/rotate-3d.ts';
export { default as Icon12Hours } from './icons/hours-12.ts';
export { default as Icon24Hours } from './icons/hours-24.ts';
export { default as Icon360View } from './icons/view-360-number.ts';
export { default as IconCircle0 } from './icons/circle-number-0.ts';
export { default as IconCircle1 } from './icons/circle-number-1.ts';
export { default as IconCircle2 } from './icons/circle-number-2.ts';
export { default as IconCircle3 } from './icons/circle-number-3.ts';
export { default as IconCircle4 } from './icons/circle-number-4.ts';
export { default as IconCircle5 } from './icons/circle-number-5.ts';
export { default as IconCircle6 } from './icons/circle-number-6.ts';
export { default as IconCircle7 } from './icons/circle-number-7.ts';
export { default as IconCircle8 } from './icons/circle-number-8.ts';
export { default as IconCircle9 } from './icons/circle-number-9.ts';
export { default as IconHexagon0 } from './icons/hexagon-number-0.ts';
export { default as IconHexagon1 } from './icons/hexagon-number-1.ts';
export { default as IconHexagon2 } from './icons/hexagon-number-2.ts';
export { default as IconHexagon3 } from './icons/hexagon-number-3.ts';
export { default as IconHexagon4 } from './icons/hexagon-number-4.ts';
export { default as IconHexagon5 } from './icons/hexagon-number-5.ts';
export { default as IconHexagon6 } from './icons/hexagon-number-6.ts';
export { default as IconHexagon7 } from './icons/hexagon-number-7.ts';
export { default as IconHexagon8 } from './icons/hexagon-number-8.ts';
export { default as IconHexagon9 } from './icons/hexagon-number-9.ts';
export { default as IconSquare0 } from './icons/square-number-0.ts';
export { default as IconSquare1 } from './icons/square-number-1.ts';
export { default as IconSquare2 } from './icons/square-number-2.ts';
export { default as IconSquare3 } from './icons/square-number-3.ts';
export { default as IconSquare4 } from './icons/square-number-4.ts';
export { default as IconSquare5 } from './icons/square-number-5.ts';
export { default as IconSquare6 } from './icons/square-number-6.ts';
export { default as IconSquare7 } from './icons/square-number-7.ts';
export { default as IconSquare8 } from './icons/square-number-8.ts';
export { default as IconSquare9 } from './icons/square-number-9.ts';
export { default as IconMessageCircle2 } from './icons/message-circle.ts';
export { default as IconMoodSuprised } from './icons/mood-surprised.ts';
export { default as IconCircleDashedLetterLetterV } from './icons/circle-dashed-letter-v.ts';
export { default as IconSeeding } from './icons/seedling.ts';
export { default as IconSeedingOff } from './icons/seedling-off.ts';
export { default as IconBrandAdobePremier } from './icons/brand-adobe-premiere.ts';
export { default as IconDiscountCheckFilled } from './icons/rosette-discount-check-filled.ts';
export { default as IconMessageCircle2Filled } from './icons/message-circle-filled.ts';
export { default as IconSeedingFilled } from './icons/seedling-filled.ts';

View File

@ -0,0 +1,40 @@
import type { AstroComponentFactory } from 'astro/runtime/server/render/astro/factory.js';
import type { IconNode } from './types';
import { render, renderSlot, createComponent, renderComponent } from 'astro/compiler-runtime';
import Icon from './Icon.astro';
const toKebabCase = (string: string): string =>
string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
export default (
iconName: string,
iconNode: IconNode,
type: 'outline' | 'filled' = 'outline',
): AstroComponentFactory => {
const Component = createComponent(
($$result: any, $$props: Record<string, any>, $$slots: any) => {
const { class: className, ...restProps } = $$props;
const classes = [
Boolean(iconName) && `tabler-icon-${toKebabCase(iconName)}`,
Boolean(className) && className,
].filter(Boolean).join(' ').trim();
return render`${renderComponent(
$$result,
'Icon',
Icon,
{
type,
class: classes || undefined,
iconNode,
...restProps,
},
{ default: () => render`${renderSlot($$result, $$slots['default'])}` },
)}`;
},
undefined,
'none',
);
return Component;
};

View File

@ -0,0 +1,26 @@
import type { SVGAttributes } from './types';
const defaultAttributes: Record<'outline' | 'filled', SVGAttributes> = {
outline: {
xmlns: 'http://www.w3.org/2000/svg',
width: 24,
height: 24,
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
'stroke-width': 2,
'stroke-linecap': 'round',
'stroke-linejoin': 'round',
},
filled: {
xmlns: 'http://www.w3.org/2000/svg',
width: 24,
height: 24,
viewBox: '0 0 24 24',
fill: 'currentColor',
stroke: 'none',
},
};
export default defaultAttributes;

8
packages/icons-astro/src/env.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/// <reference types="astro/client" />
declare module '*.astro' {
import type { AstroComponentFactory } from 'astro/runtime/server';
const Component: AstroComponentFactory;
export default Component;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
export * from './icons/index';
export * as icons from './icons/index';
export * from './aliases';
export * from './types';
export { default as defaultAttributes } from './defaultAttributes';
export { default as createTablerIcon } from './createTablerIcon';
export { default as Icon } from './Icon.astro';

View File

@ -0,0 +1,78 @@
import type { HTMLAttributes } from 'astro/types';
// Type that the Astro language server needs to infer component props in Astro files
export type AstroComponent = (_props: IconProps) => any;
export interface IconProps extends Omit<SVGAttributes, 'stroke' | 'stroke-width'> {
type?: 'outline' | 'filled';
color?: string;
size?: number | string;
stroke?: number | string;
'stroke-width'?: number | string;
class?: string;
iconNode?: IconNode;
}
export type SVGAttributes = HTMLAttributes<'svg'>;
export type IconNode = IconNodeChild[];
export type IconNodeChild = [elementName: SVGElements, attrs: SVGAttributes];
// All possible svg elements according to the Astro definitions
type SVGElements =
| 'svg'
| 'animate'
| 'circle'
| 'clipPath'
| 'defs'
| 'desc'
| 'ellipse'
| 'feBlend'
| 'feColorMatrix'
| 'feComponentTransfer'
| 'feComposite'
| 'feConvolveMatrix'
| 'feDiffuseLighting'
| 'feDisplacementMap'
| 'feDistantLight'
| 'feFlood'
| 'feFuncA'
| 'feFuncB'
| 'feFuncG'
| 'feFuncR'
| 'feGaussianBlur'
| 'feImage'
| 'feMerge'
| 'feMergeNode'
| 'feMorphology'
| 'feOffset'
| 'fePointLight'
| 'feSpecularLighting'
| 'feSpotLight'
| 'feTile'
| 'feTurbulence'
| 'filter'
| 'foreignObject'
| 'g'
| 'image'
| 'line'
| 'linearGradient'
| 'marker'
| 'mask'
| 'metadata'
| 'path'
| 'pattern'
| 'polygon'
| 'polyline'
| 'radialGradient'
| 'rect'
| 'stop'
| 'switch'
| 'symbol'
| 'text'
| 'textPath'
| 'tspan'
| 'use'
| 'view';

View File

@ -0,0 +1,26 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"useDefineForClassFields": true,
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"verbatimModuleSyntax": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"checkJs": true,
"noEmit": true,
"skipLibCheck": true,
"jsx": "preserve",
"lib": ["ESNext", "DOM.Iterable"],
"types": ["@testing-library/jest-dom"],
"plugins": [
{
"name": "@astrojs/ts-plugin",
},
],
},
"include": ["src/**/*.ts", "src/**/*.astro", "tests/**/*.ts"],
}

File diff suppressed because it is too large Load Diff

20
test/test-astro/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
# build output
dist/
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store

28
test/test-astro/README.md Normal file
View File

@ -0,0 +1,28 @@
# Test Astro
Test project for @tabler/icons-astro package.
## Usage
```bash
# Install dependencies
pnpm install
# Run dev server
pnpm dev
# Build
pnpm build
# Preview build
pnpm preview
```
## Examples
The test page demonstrates:
- Outline icons with different stroke widths
- Filled icons
- Different sizes
- Custom colors

View File

@ -0,0 +1,14 @@
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({
vite: {
optimizeDeps: {
include: ['@tabler/icons-astro'],
},
ssr: {
noExternal: ['@tabler/icons-astro'],
},
},
});

View File

@ -0,0 +1,20 @@
{
"name": "test-astro",
"private": true,
"version": "3.36.0",
"type": "module",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"clean": "rm -rf dist .astro"
},
"dependencies": {
"@tabler/icons-astro": "workspace:*",
"astro": "^5.16.6"
},
"devDependencies": {
"@astrojs/ts-plugin": "^1.10.6"
}
}

View File

@ -0,0 +1,85 @@
---
import { IconAd, IconAdOff, IconAdFilled } from '@tabler/icons-astro/icons';
---
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
.App {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
</style>
</head>
<body>
<div class="App">
<a id="toggle-icon">
<IconAd size={48} id="icon-ad" />
<IconAdOff size={48} id="icon-ad-off" style="display: none;" />
</a>
<IconAd size={48} stroke={1} />
<IconAdOff size={48} stroke={1.5} />
<IconAdFilled size={48} type="filled" />
</div>
<script>
let active = false;
const toggleButton = document.getElementById('toggle-icon');
const iconAd = document.getElementById('icon-ad');
const iconAdOff = document.getElementById('icon-ad-off');
if (toggleButton && iconAd && iconAdOff) {
toggleButton.addEventListener('click', () => {
active = !active;
if (active) {
iconAd.style.display = 'none';
iconAdOff.style.display = 'inline-block';
} else {
iconAd.style.display = 'inline-block';
iconAdOff.style.display = 'none';
}
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,8 @@
{
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "astro"
}
}