diff --git a/package.json b/package.json
index 797156a0..e489bf73 100644
--- a/package.json
+++ b/package.json
@@ -76,6 +76,7 @@
"bumpp": "^10.1.0",
"chalk": "^4.1.2",
"commit-and-tag-version": "^12.5.0",
+ "country-flag-icons": "^1.6.20",
"dotenv": "^16.4.7",
"eslint": "^9.39.4",
"eslint-config-prettier": "^9.1.2",
diff --git a/packages/components/src/components/Flag/Flag.mdx b/packages/components/src/components/Flag/Flag.mdx
new file mode 100644
index 00000000..4d7a4220
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.mdx
@@ -0,0 +1,130 @@
+import {
+ Meta,
+ Story,
+ Props,
+ Status,
+} from '../../../../../.storybook/components';
+
+import * as Stories from './Flag.stories';
+
+
+
+# Flag
+
+
+
+Flag shows a small country flag inside a product UI (inline with text, in lists, options, selects).
+
+It is a thin presentational wrapper: it decorates a flag graphic you provide and does **not** ship
+or resolve any flag data. Flag graphics are expected to come from
+[`country-flag-icons`](https://www.npmjs.com/package/country-flag-icons) (full ISO 3166-1, redrawn
+for small sizes) or any custom source.
+
+## Import
+
+```tsx
+import { Flag } from '@koobiq/react-components';
+```
+
+## Usage
+
+Provide the flag graphic as `children`. The recommended path is a ready-made React flag component
+from [`country-flag-icons`](https://www.npmjs.com/package/country-flag-icons) — no extra requests, no
+base64, and it renders an inline `` under the hood. A raw inline `` or an ` ` also
+works.
+
+```tsx
+import { DE } from 'country-flag-icons/react/3x2';
+
+
+
+ ;
+```
+
+
+
+## Props
+
+
+
+## Shape
+
+The `shape` prop controls the corner treatment: `rectangle` (default) or `circle`. `circle` clips the
+flag to a circle and defaults its ratio to `1 / 1`. For a sharp-cornered square, use
+`aspectRatio="1 / 1"` (see below).
+
+
+
+## Shadow
+
+A thin inset hairline separates the flag from the background. It is on by default and adapts to the theme (dark hairline in the light theme, lighter in the dark theme).
+
+
+
+## Sizing
+
+By default the flag's height is `1em`, so it tracks the surrounding text — inline, in lists, and in
+options you set nothing. For an explicit height use the `size` prop (a number is pixels, a string is
+any CSS length), or override the `--kbq-flag-size` variable to size a whole context at once.
+
+```tsx
+ // 24px
+ // any CSS length
+```
+
+
+
+## Aspect ratio
+
+Set the box ratio with the `aspectRatio` prop.
+
+
+
+## Missing flag
+
+The library ships no flag data, so guard the country code (e.g. with `hasFlag` from
+`country-flag-icons`) and render a neutral placeholder when a flag is missing —
+the layout never breaks and no broken graphic is shown.
+
+
+
+## Accessibility
+
+A flag must never be a silent, meaning-bearing graphic. Flag adds no ARIA semantics on its own —
+supply them with standard attributes:
+
+- When the flag carries meaning and has **no adjacent text**, pass a `aria-label` and `role="img"`.
+- When adjacent visible text already names the country, mark the flag with `aria-hidden="true"`. It is hidden from
+ assistive technology to avoid duplication.
+
+
+
+## Flag is not a language
+
+A flag represents a country, not a language. Use a globe icon (not a flag) for language selection.
+
+
+
+## Custom look
+
+Stylized, decorative treatments (rounded corners, drop shadow, "folds" gradient) are your own CSS
+plus the exposed variables — not a library prop. Round the corners with `--kbq-flag-border-radius`
+and add a shadow/gradient in your own styles.
+
+
+
+## Flags in a Select
+
+
+
+## CSS variables
+
+Everything visual that isn't a discrete state is an overridable CSS variable:
+
+| Variable | Default | Purpose |
+| ----------------------------- | --------------------------------------- | ----------------------------------------------------- |
+| `--kbq-flag-size` | `1em` | Flag height (also settable via the `size` prop). |
+| `--kbq-flag-aspect-ratio` | `3 / 2` | Box ratio (also settable via the `aspectRatio` prop). |
+| `--kbq-flag-border-radius` | `0` | Corner radius (rounded / stylized look). |
+| `--kbq-flag-shadow-color` | `var(--kbq-line-contrast-fade)` | Inset hairline color; theme-adaptive. |
+| `--kbq-flag-empty-background` | `var(--kbq-states-background-disabled)` | Placeholder fill. |
diff --git a/packages/components/src/components/Flag/Flag.module.css b/packages/components/src/components/Flag/Flag.module.css
new file mode 100644
index 00000000..5663403e
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.module.css
@@ -0,0 +1,47 @@
+.base {
+ /* Public, overridable knobs (see the component docs). */
+ --kbq-flag-aspect-ratio: 3 / 2;
+ --kbq-flag-border-radius: 0;
+ --kbq-flag-shadow-color: var(--kbq-line-contrast-fade);
+ --kbq-flag-empty-background: var(--kbq-states-background-disabled);
+
+ display: inline-block;
+ position: relative;
+ overflow: hidden;
+ vertical-align: middle;
+ block-size: var(--kbq-flag-size, 1em);
+ aspect-ratio: var(--kbq-flag-aspect-ratio);
+ border-radius: var(--kbq-flag-border-radius);
+}
+
+/* The projected flag graphic fills the box (descendant selector supports wrapped graphics). */
+.base :is(svg, img) {
+ display: block;
+ inline-size: 100%;
+ block-size: 100%;
+ object-fit: cover;
+}
+
+/* Inset hairline separating the flag from the background (shown by default). */
+.base::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ border: 1px solid var(--kbq-flag-shadow-color);
+ pointer-events: none;
+}
+
+.base[data-hide-shadow]::after {
+ content: none;
+}
+
+/* `circle` only clips the corners; its 1:1 ratio comes from the component. */
+.base[data-shape='circle'] {
+ border-radius: 50%;
+}
+
+/* No projected graphic → neutral placeholder (e.g. unknown/invalid country). */
+.base:empty {
+ background-color: var(--kbq-flag-empty-background);
+}
diff --git a/packages/components/src/components/Flag/Flag.stories.module.css b/packages/components/src/components/Flag/Flag.stories.module.css
new file mode 100644
index 00000000..76e1d18e
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.stories.module.css
@@ -0,0 +1,21 @@
+/* Gradient imitating folds, blended over the flag (stylized docs example). */
+.stylized::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ z-index: 1;
+ border-radius: inherit;
+ background: linear-gradient(
+ 240.64deg,
+ rgb(255 255 255 / 30%) 0%,
+ rgb(0 0 0 / 27%) 26.27%,
+ rgb(255 255 255 / 26%) 37%,
+ rgb(0 0 0 / 55%) 48.7%,
+ rgb(0 0 0 / 24%) 59.44%,
+ rgb(255 255 255 / 30%) 73.64%,
+ rgb(39 39 39 / 22%) 90.15%,
+ rgb(0 0 0 / 20%) 100%
+ );
+ mix-blend-mode: overlay;
+ pointer-events: none;
+}
diff --git a/packages/components/src/components/Flag/Flag.stories.tsx b/packages/components/src/components/Flag/Flag.stories.tsx
new file mode 100644
index 00000000..35276ac2
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.stories.tsx
@@ -0,0 +1,322 @@
+import { type CSSProperties } from 'react';
+
+import { IconGlobe16 } from '@koobiq/react-icons';
+import type { Meta, StoryObj } from '@storybook/react';
+import { hasFlag } from 'country-flag-icons';
+import { DE as DE1x1 } from 'country-flag-icons/react/1x1';
+import { BR, DE, FR, JP, US } from 'country-flag-icons/react/3x2';
+
+import { FlexBox } from '../FlexBox';
+import { SelectNext as Select } from '../SelectNext';
+import { Typography } from '../Typography';
+
+import s from './Flag.stories.module.css';
+import {
+ Flag,
+ type FlagProps,
+ flagPropShape,
+ flagPropAspectRatio,
+} from './index.js';
+
+// These small maps let examples look up a flag by ISO code.
+const flags3x2 = { BR, DE, FR, JP, US };
+const flags1x1 = { DE: DE1x1 };
+
+const meta = {
+ title: 'Components/Flag',
+ component: Flag,
+ parameters: {
+ layout: 'centered',
+ },
+ argTypes: {
+ shape: {
+ options: flagPropShape,
+ control: { type: 'inline-radio' },
+ },
+ aspectRatio: {
+ options: flagPropAspectRatio,
+ control: { type: 'select' },
+ },
+ },
+ tags: ['status:new', 'date:2026-07-10'],
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Base: Story = {
+ render: (args) => (
+
+
+
+ ),
+};
+
+export const Shape: Story = {
+ render: (args) => (
+
+ {flagPropShape.map((shape) => (
+
+
+
+
+ {shape}
+
+ ))}
+
+
+
+
+ square
+
+
+ ),
+};
+
+export const Shadow: Story = {
+ render: (args) => (
+
+ {[false, true].map((hideShadow) => (
+
+
+
+
+
+ hideShadow = {String(hideShadow)}
+
+
+ ))}
+
+ ),
+};
+
+export const Empty: Story = {
+ render: (args) => (
+
+ ),
+};
+
+/**
+ * The library ships no flag data, so guard the code with `hasFlag` and render a
+ * neutral placeholder (or your own glyph) when a flag is missing.
+ */
+export const Fallback: Story = {
+ render: (args) => (
+
+ {['DE', 'ZZ'].map((code) => {
+ const known = hasFlag(code);
+ const FlagIcon = flags3x2[code as keyof typeof flags3x2];
+
+ return (
+
+
+ {known ? : null}
+
+ {code}
+
+ );
+ })}
+
+ ),
+};
+
+/**
+ * Flag adds no ARIA semantics on its own — supply them with standard attributes:
+ * `role="img"` + `aria-label` for a meaningful flag with no adjacent text,
+ * `aria-labelledby` when visible text names it, or `aria-hidden` when it is
+ * purely decorative.
+ */
+export const Accessibility: Story = {
+ render: (args) => (
+
+ {/* Meaningful flag, no adjacent text. */}
+
+
+
+
+ {/* Decorative flag beside visible text. */}
+
+
+
+
+ Germany
+
+
+ ),
+};
+
+/**
+ * Set an explicit height with the `size` prop (a number is pixels, a string is
+ * any CSS length). Omit it and the flag defaults to `1em`, tracking the text.
+ */
+export const Sizes: Story = {
+ render: (args) => (
+
+ {[16, 24, 32, 48].map((size) => (
+
+
+
+ ))}
+
+ ),
+};
+
+/**
+ * Set the box ratio with the `aspectRatio` prop — common presets plus any CSS
+ * value. The graphic is cropped to fill (`object-fit: cover`).
+ */
+export const AspectRatio: Story = {
+ render: (args) => (
+
+
+
+
+
+
+
+
+
+ 4 / 3
+
+
+ ),
+};
+
+/**
+ * A stylized, volumetric look is consumer CSS — rounded corners via
+ * `--kbq-flag-border-radius`, plus a drop shadow and a "folds" gradient overlay.
+ */
+export const Custom: Story = {
+ render: (args) => (
+
+
+
+ ),
+};
+
+// Languages are picked with a neutral globe icon, not a flag:
+// one language spans several countries.
+const languages = [
+ 'English (UK)',
+ 'English (US)',
+ 'Español',
+ 'Français',
+ 'Русский',
+ 'हिन्दी',
+ '中文',
+];
+
+/**
+ * A flag represents a country, not a language. Use a globe icon (not a flag) for
+ * language selection.
+ */
+export const NotForLanguage: Story = {
+ render: () => (
+ }
+ style={{ inlineSize: 320 }}
+ defaultValue={languages[0]}
+ >
+ {languages.map((language) => (
+
+ {language}
+
+ ))}
+
+ ),
+};
+
+const countries = [
+ { code: 'DE', name: 'Germany' },
+ { code: 'FR', name: 'France' },
+ { code: 'JP', name: 'Japan' },
+ { code: 'US', name: 'United States' },
+ { code: 'BR', name: 'Brazil' },
+];
+
+const CountryOption = ({ code, name }: { code: string; name: string }) => {
+ const FlagIcon = flags3x2[code as keyof typeof flags3x2];
+
+ return (
+
+
+
+
+ {name}
+
+ );
+};
+
+export const FlagsInSelect: Story = {
+ render: () => (
+ {
+ const item = state.selectedItems?.[0];
+
+ if (!item) return null;
+
+ return (
+
+ );
+ }}
+ >
+ {countries.map(({ code, name }) => (
+
+
+
+ ))}
+
+ ),
+};
diff --git a/packages/components/src/components/Flag/Flag.test.tsx b/packages/components/src/components/Flag/Flag.test.tsx
new file mode 100644
index 00000000..67e3d3c7
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.test.tsx
@@ -0,0 +1,155 @@
+import { createRef } from 'react';
+
+import { screen, render } from '@testing-library/react';
+import { describe, it, expect } from 'vitest';
+
+import { Flag, flagPropShape } from './index.js';
+
+describe('Flag', () => {
+ const baseProps = { 'data-testid': 'flag' };
+
+ const getRoot = () => screen.getByTestId('flag');
+
+ it('should receive ref', () => {
+ const ref = createRef();
+ const { container } = render( );
+ const flag = container.querySelector('span');
+ expect(ref.current).toBe(flag);
+ });
+
+ it('should render the component as a div with the correct tag', () => {
+ const ref = createRef();
+
+ render( );
+
+ expect(getRoot().tagName).toBe('DIV');
+ });
+
+ it('should project the flag graphic', () => {
+ render(
+
+
+
+ );
+
+ expect(screen.getByTestId('graphic')).toBeInTheDocument();
+ });
+
+ describe('check the shape prop', () => {
+ it('should default to the rectangle shape', () => {
+ render( );
+
+ expect(getRoot()).toHaveAttribute('data-shape', 'rectangle');
+ });
+
+ it.each(flagPropShape)('should apply the shape as a "%s"', (shape) => {
+ render( );
+
+ expect(getRoot()).toHaveAttribute('data-shape', shape);
+ });
+ });
+
+ describe('check the hideShadow prop', () => {
+ it('should show the shadow by default', () => {
+ render( );
+
+ expect(getRoot()).not.toHaveAttribute('data-hide-shadow');
+ });
+
+ it('should set data-hide-shadow when hideShadow is true', () => {
+ render( );
+
+ expect(getRoot()).toHaveAttribute('data-hide-shadow', 'true');
+ });
+ });
+
+ describe('check the size prop', () => {
+ it('should not set --kbq-flag-size by default', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-size')).toBe('');
+ });
+
+ it('should set --kbq-flag-size in pixels for a number', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-size')).toBe('24px');
+ });
+
+ it('should set --kbq-flag-size verbatim for a string', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-size')).toBe('2rem');
+ });
+
+ it('should merge with the consumer style', () => {
+ render( );
+
+ const flag = getRoot();
+
+ expect(flag.style.getPropertyValue('--kbq-flag-size')).toBe('24px');
+ expect(flag.style.color).toBe('red');
+ });
+ });
+
+ describe('check the aspectRatio prop', () => {
+ it('should not set --kbq-flag-aspect-ratio by default', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-aspect-ratio')).toBe(
+ ''
+ );
+ });
+
+ it('should set --kbq-flag-aspect-ratio from a string', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-aspect-ratio')).toBe(
+ '4 / 3'
+ );
+ });
+
+ it('should default the ratio to 1 / 1 for a circle', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-aspect-ratio')).toBe(
+ '1 / 1'
+ );
+ });
+
+ it('should let an explicit aspectRatio override the circle default', () => {
+ render( );
+
+ expect(getRoot().style.getPropertyValue('--kbq-flag-aspect-ratio')).toBe(
+ '4 / 3'
+ );
+ });
+ });
+
+ describe('accessibility attributes', () => {
+ it('should forward role and aria-label for a meaningful flag', () => {
+ render( );
+
+ const flag = getRoot();
+
+ expect(flag).toHaveAttribute('role', 'img');
+ expect(flag).toHaveAttribute('aria-label', 'Germany');
+ });
+
+ it('should forward aria-hidden for a decorative flag', () => {
+ render( );
+
+ expect(getRoot()).toHaveAttribute('aria-hidden', 'true');
+ });
+
+ it('should add no role or aria attributes by default', () => {
+ render( );
+
+ const flag = getRoot();
+
+ expect(flag).not.toHaveAttribute('role');
+ expect(flag).not.toHaveAttribute('aria-label');
+ expect(flag).not.toHaveAttribute('aria-hidden');
+ });
+ });
+});
diff --git a/packages/components/src/components/Flag/Flag.tsx b/packages/components/src/components/Flag/Flag.tsx
new file mode 100644
index 00000000..02c3fa79
--- /dev/null
+++ b/packages/components/src/components/Flag/Flag.tsx
@@ -0,0 +1,58 @@
+'use client';
+
+import type { ComponentPropsWithRef, CSSProperties, ElementType } from 'react';
+
+import { clsx, isNumber, polymorphicForwardRef } from '@koobiq/react-core';
+
+import s from './Flag.module.css';
+import type { FlagBaseProps } from './index';
+
+/**
+ * Flag is a thin presentational wrapper that decorates a country flag graphic
+ * provided by the consumer (inline `svg`, `img` or SVG component). It holds no flag data.
+ *
+ * Flag adds no ARIA semantics on its own. Supply them via standard attributes:
+ * `role="img"` + `aria-label` / `aria-labelledby` for a meaningful flag, or
+ * `aria-hidden` for a decorative one.
+ */
+export const Flag = polymorphicForwardRef<'span', FlagBaseProps>(
+ (props, ref) => {
+ const {
+ as: Tag = 'span',
+ shape = 'rectangle',
+ hideShadow = false,
+ size,
+ // `circle` needs a 1:1 box; an explicit `aspectRatio` still wins.
+ aspectRatio = shape === 'circle' ? '1 / 1' : undefined,
+ style,
+ className,
+ children,
+ ...other
+ } = props;
+
+ const flagStyle = {
+ ...style,
+ ...(size !== undefined && {
+ '--kbq-flag-size': isNumber(size) ? `${size}px` : size,
+ }),
+ ...(aspectRatio && { '--kbq-flag-aspect-ratio': aspectRatio }),
+ } as CSSProperties;
+
+ return (
+
+ {children}
+
+ );
+ }
+);
+
+export type FlagProps = ComponentPropsWithRef<
+ typeof Flag
+>;
diff --git a/packages/components/src/components/Flag/index.ts b/packages/components/src/components/Flag/index.ts
new file mode 100644
index 00000000..72d69f0b
--- /dev/null
+++ b/packages/components/src/components/Flag/index.ts
@@ -0,0 +1,2 @@
+export * from './Flag';
+export * from './types';
diff --git a/packages/components/src/components/Flag/types.ts b/packages/components/src/components/Flag/types.ts
new file mode 100644
index 00000000..0ef4bd1b
--- /dev/null
+++ b/packages/components/src/components/Flag/types.ts
@@ -0,0 +1,41 @@
+import type { CSSProperties, ReactNode } from 'react';
+
+export const flagPropShape = ['rectangle', 'circle'] as const;
+
+export type FlagPropShape = (typeof flagPropShape)[number];
+
+export const flagPropAspectRatio = ['3 / 2', '1 / 1'] as const;
+
+export type FlagPropAspectRatio = (typeof flagPropAspectRatio)[number];
+
+export type FlagBaseProps = {
+ /**
+ * The corner treatment of the flag. `circle` clips it to a circle (its
+ * aspect ratio defaults to `1 / 1`).
+ * @default 'rectangle'
+ */
+ shape?: FlagPropShape;
+ /**
+ * Hides the inset hairline that separates the flag from the background.
+ * @default false
+ */
+ hideShadow?: boolean;
+ /**
+ * The size of the flag (its height). A `number` is treated as pixels, a
+ * `string` is used as-is (any CSS length). Defaults to `1em`, so the flag
+ * tracks the surrounding text.
+ */
+ size?: number | string;
+ /**
+ * The box aspect ratio. Common presets are offered, but any CSS
+ * `aspect-ratio` value works (e.g. `4 / 3`).
+ * @default '3 / 2' (`'1 / 1'` when `shape="circle"`)
+ */
+ aspectRatio?: FlagPropAspectRatio | CSSProperties['aspectRatio'];
+ /** The projected flag graphic (inline `svg` or `img`). */
+ children?: ReactNode;
+ /** Additional CSS-classes. */
+ className?: string;
+ /** Inline styles. */
+ style?: CSSProperties;
+};
diff --git a/packages/components/src/components/index.ts b/packages/components/src/components/index.ts
index 9cb9d87c..b02814d8 100644
--- a/packages/components/src/components/index.ts
+++ b/packages/components/src/components/index.ts
@@ -54,6 +54,7 @@ export * from './ActionsPanel';
export * from './Tree';
export * from './TreeSelect';
export * from './EmptyState';
+export * from './Flag';
export * from './layout';
export {
useListData,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 21abf963..a0dea05c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -118,6 +118,9 @@ importers:
commit-and-tag-version:
specifier: ^12.5.0
version: 12.5.0
+ country-flag-icons:
+ specifier: ^1.6.20
+ version: 1.6.20
dotenv:
specifier: ^16.4.7
version: 16.4.7
@@ -4196,10 +4199,12 @@ packages:
conventional-changelog-atom@3.0.0:
resolution: {integrity: sha512-pnN5bWpH+iTUWU3FaYdw5lJmfWeqSyrUkG+wyHBI9tC1dLNnHkbAOg1SzTQ7zBqiFrfo55h40VsGXWMdopwc5g==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-codemirror@3.0.0:
resolution: {integrity: sha512-wzchZt9HEaAZrenZAUUHMCFcuYzGoZ1wG/kTRMICxsnW5AXohYMRxnyecP9ob42Gvn5TilhC0q66AtTPRSNMfw==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-config-spec@2.1.0:
resolution: {integrity: sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==}
@@ -4215,26 +4220,32 @@ packages:
conventional-changelog-core@5.0.2:
resolution: {integrity: sha512-RhQOcDweXNWvlRwUDCpaqXzbZemKPKncCWZG50Alth72WITVd6nhVk9MJ6w1k9PFNBcZ3YwkdkChE+8+ZwtUug==}
engines: {node: '>=14'}
+ deprecated: Deprecated and no longer maintained. Please use conventional-changelog instead.
conventional-changelog-ember@3.0.0:
resolution: {integrity: sha512-7PYthCoSxIS98vWhVcSphMYM322OxptpKAuHYdVspryI0ooLDehRXWeRWgN+zWSBXKl/pwdgAg8IpLNSM1/61A==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-eslint@4.0.0:
resolution: {integrity: sha512-nEZ9byP89hIU0dMx37JXQkE1IpMmqKtsaR24X7aM3L6Yy/uAtbb+ogqthuNYJkeO1HyvK7JsX84z8649hvp43Q==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-express@3.0.0:
resolution: {integrity: sha512-HqxihpUMfIuxvlPvC6HltA4ZktQEUan/v3XQ77+/zbu8No/fqK3rxSZaYeHYant7zRxQNIIli7S+qLS9tX9zQA==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-jquery@4.0.0:
resolution: {integrity: sha512-TTIN5CyzRMf8PUwyy4IOLmLV2DFmPtasKN+x7EQKzwSX8086XYwo+NeaeA3VUT8bvKaIy5z/JoWUvi7huUOgaw==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-jshint@3.0.0:
resolution: {integrity: sha512-bQof4byF4q+n+dwFRkJ/jGf9dCNUv4/kCDcjeCizBvfF81TeimPZBB6fT4HYbXgxxfxWXNl/i+J6T0nI4by6DA==}
engines: {node: '>=14'}
+ deprecated: This preset is deprecated. Please use conventional-changelog-conventionalcommits or conventional-changelog-angular instead.
conventional-changelog-preset-loader@3.0.0:
resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==}
@@ -4306,6 +4317,9 @@ packages:
typescript:
optional: true
+ country-flag-icons@1.6.20:
+ resolution: {integrity: sha512-py8JiEKzjhYw6HPJ0L7SxLgCYim36UPRTZX43/kqGueUCZLSvnrqAiwW8HtQibur7mdkFQUkjOgdK+o/9FBtaw==}
+
crc-32@1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'}
@@ -5283,13 +5297,13 @@ packages:
git-raw-commits@3.0.0:
resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==}
engines: {node: '>=14'}
- deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.
+ deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.
hasBin: true
git-raw-commits@4.0.0:
resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==}
engines: {node: '>=16'}
- deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.
+ deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.
hasBin: true
git-remote-origin-url@2.0.0:
@@ -5299,7 +5313,7 @@ packages:
git-semver-tags@5.0.1:
resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==}
engines: {node: '>=14'}
- deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead.
+ deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.
hasBin: true
gitconfiglocal@1.0.0:
@@ -13228,6 +13242,8 @@ snapshots:
optionalDependencies:
typescript: 6.0.3
+ country-flag-icons@1.6.20: {}
+
crc-32@1.2.2: {}
crc32-stream@6.0.0:
diff --git a/tools/api-extractor/config.json b/tools/api-extractor/config.json
index 202e10d5..4faa8ef5 100644
--- a/tools/api-extractor/config.json
+++ b/tools/api-extractor/config.json
@@ -18,6 +18,7 @@
"DatePicker",
"Divider",
"EmptyState",
+ "Flag",
"FlexBox",
"Form",
"FormField",
diff --git a/tools/public_api_guard/components/Flag.api.md b/tools/public_api_guard/components/Flag.api.md
new file mode 100644
index 00000000..91193afb
--- /dev/null
+++ b/tools/public_api_guard/components/Flag.api.md
@@ -0,0 +1,44 @@
+## API Report File for "koobiq-react"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+
+import type { ComponentPropsWithRef } from 'react';
+import type { CSSProperties } from 'react';
+import type { ElementType } from 'react';
+import { PolyForwardComponent } from '@koobiq/react-core';
+import type { ReactNode } from 'react';
+
+// @public
+export const Flag: PolyForwardComponent<"span", FlagBaseProps, ElementType>;
+
+// @public (undocumented)
+export type FlagBaseProps = {
+ shape?: FlagPropShape;
+ hideShadow?: boolean;
+ size?: number | string;
+ aspectRatio?: FlagPropAspectRatio | CSSProperties['aspectRatio'];
+ children?: ReactNode;
+ className?: string;
+ style?: CSSProperties;
+};
+
+// @public (undocumented)
+export type FlagPropAspectRatio = (typeof flagPropAspectRatio)[number];
+
+// @public (undocumented)
+export const flagPropAspectRatio: readonly ["3 / 2", "1 / 1"];
+
+// @public (undocumented)
+export type FlagProps = ComponentPropsWithRef>;
+
+// @public (undocumented)
+export type FlagPropShape = (typeof flagPropShape)[number];
+
+// @public (undocumented)
+export const flagPropShape: readonly ["rectangle", "circle"];
+
+// (No @packageDocumentation comment for this package)
+
+```