@charcoal-ui/icons 1.0.0 → 1.0.1-alpha.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/PixivIcon.d.ts +3 -2
- package/dist/PixivIcon.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.modern.js +1 -14
- package/dist/index.modern.js.map +1 -1
- package/dist/index.module.js +1 -1
- package/dist/index.module.js.map +1 -1
- package/dist/loaders.d.ts.map +1 -1
- package/dist/ssr.d.ts +11 -0
- package/dist/ssr.d.ts.map +1 -0
- package/package.json +10 -3
- package/src/PixivIcon.ts +32 -20
- package/src/index.ts +7 -4
- package/src/loaders.ts +1 -0
- package/src/ssr.ts +12 -0
package/dist/PixivIcon.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { KnownIconFile } from './filenames';
|
|
3
|
+
import { BaseElement } from './ssr';
|
|
3
4
|
export interface KnownIconType extends Record<KnownIconFile, unknown> {
|
|
4
5
|
}
|
|
5
6
|
export interface Props extends Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, 'className'> {
|
|
@@ -10,7 +11,7 @@ export interface Props extends Omit<React.DetailedHTMLProps<React.HTMLAttributes
|
|
|
10
11
|
}
|
|
11
12
|
declare type ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>;
|
|
12
13
|
declare type Extended = [ExtendedIconFile] extends [never] ? false : true;
|
|
13
|
-
export declare class PixivIcon extends
|
|
14
|
+
export declare class PixivIcon extends BaseElement {
|
|
14
15
|
static readonly tagName = "pixiv-icon";
|
|
15
16
|
static extend(map: Extended extends true ? Record<ExtendedIconFile, string> : Record<string, string>): void;
|
|
16
17
|
static get observedAttributes(): readonly ["name", "scale", "unsafe-non-guideline-scale"];
|
|
@@ -27,7 +28,7 @@ export declare class PixivIcon extends HTMLElement {
|
|
|
27
28
|
connectedCallback(): void;
|
|
28
29
|
disconnectedCallback(): void;
|
|
29
30
|
attributeChangedCallback(): void;
|
|
30
|
-
render():
|
|
31
|
+
render(): void;
|
|
31
32
|
private update;
|
|
32
33
|
private waitUntilVisible;
|
|
33
34
|
}
|
package/dist/PixivIcon.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PixivIcon.d.ts","sourceRoot":"","sources":["../src/PixivIcon.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PixivIcon.d.ts","sourceRoot":"","sources":["../src/PixivIcon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,EAAE,WAAW,EAAc,MAAM,OAAO,CAAA;AAS/C,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC;CAAG;AAExE,MAAM,WAAW,KACf,SAAQ,IAAI,CACV,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,EACvE,WAAW,CACZ;IACD,IAAI,EAAE,MAAM,aAAa,CAAA;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACnC,4BAA4B,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAI9C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAID,aAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,aAAa,EAAE,aAAa,CAAC,CAAA;AACnE,aAAK,QAAQ,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,GAC9C,KAAK,GACL,IAAI,CAAA;AAER,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,CAAC,QAAQ,CAAC,OAAO,gBAAe;IAEtC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,SAAS,IAAI,GACtB,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAoB5B,MAAM,KAAK,kBAAkB,6DAE5B;IAED,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAsB;IAEvC,IAAI,KAAK;;;;MAqBR;IAED,IAAI,gBAAgB,kBAiBnB;IAED,IAAI,UAAU,WA0Bb;;IAOD,iBAAiB;IAKjB,oBAAoB;IAKpB,wBAAwB;IAIxB,MAAM;IA6BN,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,gBAAgB;CAgBzB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=require("
|
|
1
|
+
var e=require("warning"),t=require("dompurify");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function r(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,t}var o=/*#__PURE__*/n(e);function i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function u(){return u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},u.apply(this,arguments)}function c(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,a(e,t)}function s(e){return s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},s(e)}function a(e,t){return a=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},a(e,t)}function l(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function f(e,t,n){return f=l()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&a(o,n.prototype),o},f.apply(null,arguments)}function p(e){var t="function"==typeof Map?new Map:void 0;return p=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return f(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),a(n,e)},p(e)}var v=new Map,d=/*#__PURE__*/function(e){function t(n){var r;return r=e.call(this,n)||this,Object.setPrototypeOf(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(r),this instanceof t?this.constructor:void 0),r}return c(t,e),t}(/*#__PURE__*/p(Error));function h(e){return function(t){try{return v.has(t)?Promise.resolve(v.get(t)):Promise.resolve(e(t).then(function(e){return fetch(e)}).then(function(e){if(!e.ok)throw new d('Failed to fetch <pixiv-icon name="'+t+'">');return e.text()})).then(function(e){return v.set(t,e),e})}catch(e){return Promise.reject(e)}}}var m={loadFromRawUrl:h(function(e){return Promise.resolve(e)}),loadFromFile:h(function(e){try{var t=e.split("/"),n=t[1];return Promise.resolve((o="../svg/"+encodeURIComponent(t[0])+"/"+encodeURIComponent(n)+".svg",Promise.resolve().then(function(){/*#__PURE__*/return r(require(o))}))).then(function(e){return e.default})}catch(e){return Promise.reject(e)}var o})},b="undefined"==typeof window,y="undefined"!=typeof HTMLElement,g=!b&&y?HTMLElement:/*#__PURE__*/function(){return function(){}}(),w=m.loadFromFile,O=m.loadFromRawUrl,P=["name","scale","unsafe-non-guideline-scale"],j=new Map,x=/*#__PURE__*/function(e){function n(){var t;return(t=e.call(this)||this).svgContent=void 0,t.observer=void 0,t.attachShadow({mode:"open"}),t}c(n,e),n.extend=function(e){o.default(!b,"Using `PixivIcon.extend()` on server has no effect"),b||Object.entries(e).forEach(function(e){var t=e[0],n=e[1];if(!t.includes("/"))throw new TypeError(t+' is not a valid icon name. "name" must be named like [size]/[Name].');j.set(t,function(){return O(n)})})};var r,s,a,l=n.prototype;return l.connectedCallback=function(){this.render(),this.update()},l.disconnectedCallback=function(){var e;null==(e=this.observer)||e.disconnect(),this.observer=void 0},l.attributeChangedCallback=function(){this.update()},l.render=function(){var e,n=null!=(e=this.forceResizedSize)?e:this.scaledSize,r=t.sanitize("<style>\n :host {\n display: inline-flex;\n --size: "+n+"px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>",{ALLOWED_TAGS:["style"],FORCE_BODY:!0}),o=t.sanitize(void 0!==this.svgContent?this.svgContent:'<svg viewBox="0 0 '+n+" "+n+'"></svg>',{USE_PROFILES:{svg:!0,svgFilters:!0}});this.shadowRoot.innerHTML=r+o},l.update=function(){var e=this;this.waitUntilVisible().then(function(){try{var t,n=e.props.name,r=null!=(t=j.get(n))?t:w;return Promise.resolve(r(n)).then(function(t){e.svgContent=t,e.render()})}catch(e){return Promise.reject(e)}})},l.waitUntilVisible=function(){var e=this;return new Promise(function(t){e.observer=new IntersectionObserver(function(n){var r;n[0].isIntersecting&&(null==(r=e.observer)||r.disconnect(),e.observer=void 0,t())},{rootMargin:"50px"}),e.observer.observe(e)})},r=n,a=[{key:"observedAttributes",get:function(){return P}}],(s=[{key:"props",get:function(){var e=this,t=Object.fromEntries(P.map(function(t){return[t,e.getAttribute(t)]})),n=t.name;if(null===n)throw new TypeError('property "name" is required.');if(!n.includes("/"))throw new TypeError(n+' is not a valid icon name. "name" must be named like [size]/[Name].');return u({},t,{name:n})}},{key:"forceResizedSize",get:function(){if(null===this.props["unsafe-non-guideline-scale"])return null;var e=this.props.name.split("/")[0],t=Number(this.props["unsafe-non-guideline-scale"]);return"Inline"===e?16*t:Number(e)*t}},{key:"scaledSize",get:function(){var e,t=this.props.name.split("/")[0],n=Number(null!=(e=this.props.scale)?e:"1");switch(t){case"Inline":return 2===n?32:16;case"24":return Number(t)*n;default:return Number(t)}}}])&&i(r.prototype,s),a&&i(r,a),Object.defineProperty(r,"prototype",{writable:!1}),n}(g);x.tagName="pixiv-icon",b||window.customElements.get(x.tagName)||(window.PixivIcon=x,window.customElements.define(x.tagName,x)),exports.PixivIcon=x,exports.PixivIconLoadError=d;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/loaders.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","import { html, render } from 'lit-html'\nimport { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'\nimport type React from 'react'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n return render(\n html`\n <style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n </style>\n ${this.svgContent !== undefined\n ? unsafeSVG(this.svgContent)\n : html`<svg viewBox=\"0 0 ${size} ${size}\"></svg>`}\n `,\n this.shadowRoot!\n )\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\n// TODO: HMR対応\nif (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n}\n"],"names":["cache","Map","PixivIconLoadError","message","_this","Object","setPrototypeOf","Error","createLoader","getPath","attributeName","has","get","then","path","fetch","response","ok","text","rawSvg","set","loaders","loadFromRawUrl","Promise","resolve","loadFromFile","split","name","encodeURIComponent","defaultLoaders","attributes","PixivIcon","svgContent","observer","attachShadow","mode","extend","map","entries","forEach","url","includes","TypeError","connectedCallback","this","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","size","forceResizedSize","scaledSize","html","unsafeSVG","shadowRoot","waitUntilVisible","_this2","props","loader","_this3","IntersectionObserver","isIntersecting","rootMargin","ROOT_MARGIN","observe","partial","fromEntries","attribute","_this4","getAttribute","scale","Number","HTMLElement","tagName","window","customElements","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/loaders.ts","../src/ssr.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n/**\n * NOTICE: SSR 環境では `extends HTMLElement` できない\n *\n * @see https://github.com/vuejs/core/blob/9c304bfe7942a20264235865b4bb5f6e53fdee0d/packages/runtime-dom/src/apiCustomElement.ts#L143-L145\n */\nexport const BaseElement = (\n !__SERVER__ && CAN_USE_DOM ? HTMLElement : class {}\n) as typeof HTMLElement\n","import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nimport { BaseElement, __SERVER__ } from './ssr'\nimport { sanitize } from 'dompurify'\n\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends BaseElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n"],"names":["cache","Map","PixivIconLoadError","message","_this","Object","setPrototypeOf","Error","createLoader","getPath","attributeName","has","get","then","path","fetch","response","ok","text","rawSvg","set","loaders","loadFromRawUrl","Promise","resolve","loadFromFile","split","name","encodeURIComponent","__SERVER__","window","CAN_USE_DOM","HTMLElement","BaseElement","defaultLoaders","attributes","PixivIcon","svgContent","observer","attachShadow","mode","extend","map","warning","entries","forEach","url","includes","TypeError","connectedCallback","this","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","size","forceResizedSize","scaledSize","style","sanitize","ALLOWED_TAGS","FORCE_BODY","svg","USE_PROFILES","svgFilters","shadowRoot","innerHTML","waitUntilVisible","_this2","props","loader","_this3","IntersectionObserver","isIntersecting","rootMargin","ROOT_MARGIN","observe","partial","fromEntries","attribute","_this4","getAttribute","scale","Number","tagName","customElements","define"],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,SAAS,EAAE,OAAO,SAAS,CAAA;KAC5B;IAGD,MAAM,WAAW,GAAG,CAAC;QACnB,UAAU,iBAAiB;YACzB,YAAY,EAAE,KAAK,CAAA;SACpB;KACF;CACF"}
|
package/dist/index.modern.js
CHANGED
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
<style>
|
|
3
|
-
:host {
|
|
4
|
-
display: inline-flex;
|
|
5
|
-
--size: ${0}px;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
svg {
|
|
9
|
-
width: var(--size);
|
|
10
|
-
height: var(--size);
|
|
11
|
-
}
|
|
12
|
-
</style>
|
|
13
|
-
${0}
|
|
14
|
-
`),s,void 0!==this.svgContent?n(this.svgContent):t(c||(c=u`<svg viewBox="0 0 ${0} ${0}"></svg>`),s,s)),this.shadowRoot)}update(){var e=this;this.waitUntilVisible().then(async function(){var t;const{name:n}=e.props,r=null!=(t=p.get(n))?t:d;e.svgContent=await r(n),e.render()})}waitUntilVisible(){return new Promise(e=>{this.observer=new IntersectionObserver(([t])=>{var n;t.isIntersecting&&(null==(n=this.observer)||n.disconnect(),this.observer=void 0,e())},{rootMargin:"50px"}),this.observer.observe(this)})}}v.tagName="pixiv-icon",window.customElements.get(v.tagName)||(window.PixivIcon=v,window.customElements.define(v.tagName,v));export{v as PixivIcon,i as PixivIconLoadError};
|
|
1
|
+
import e from"warning";import{sanitize as t}from"dompurify";function n(){return n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var s in n)Object.prototype.hasOwnProperty.call(n,s)&&(e[s]=n[s])}return e},n.apply(this,arguments)}const s=new Map;class r extends Error{constructor(e){super(e),Object.setPrototypeOf(this,new.target)}}function i(e){return async function(t){if(s.has(t))return s.get(t);const n=await e(t).then(e=>fetch(e)).then(e=>{if(!e.ok)throw new r(`Failed to fetch <pixiv-icon name="${t}">`);return e.text()});return s.set(t,n),n}}const o={loadFromRawUrl:i(e=>Promise.resolve(e)),loadFromFile:i(async e=>{const[t,n]=e.split("/"),{default:s}=await import(`../svg/${encodeURIComponent(t)}/${encodeURIComponent(n)}.svg`);return s})},a="undefined"==typeof window,l="undefined"!=typeof HTMLElement,c=!a&&l?HTMLElement:class{},{loadFromFile:u,loadFromRawUrl:d}=o,h=["name","scale","unsafe-non-guideline-scale"],p=new Map;class m extends c{static extend(t){e(!a,"Using `PixivIcon.extend()` on server has no effect"),a||Object.entries(t).forEach(([e,t])=>{if(!e.includes("/"))throw new TypeError(`${e} is not a valid icon name. "name" must be named like [size]/[Name].`);p.set(e,function(){return d(t)})})}static get observedAttributes(){return h}get props(){const e=Object.fromEntries(h.map(e=>[e,this.getAttribute(e)])),t=e.name;if(null===t)throw new TypeError('property "name" is required.');if(!t.includes("/"))throw new TypeError(`${t} is not a valid icon name. "name" must be named like [size]/[Name].`);return n({},e,{name:t})}get forceResizedSize(){if(null===this.props["unsafe-non-guideline-scale"])return null;const[e]=this.props.name.split("/"),t=Number(this.props["unsafe-non-guideline-scale"]);return"Inline"===e?16*t:Number(e)*t}get scaledSize(){var e;const[t]=this.props.name.split("/"),n=Number(null!=(e=this.props.scale)?e:"1");switch(t){case"Inline":return 2===n?32:16;case"24":return Number(t)*n;default:return Number(t)}}constructor(){super(),this.svgContent=void 0,this.observer=void 0,this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.update()}disconnectedCallback(){var e;null==(e=this.observer)||e.disconnect(),this.observer=void 0}attributeChangedCallback(){this.update()}render(){var e;const n=null!=(e=this.forceResizedSize)?e:this.scaledSize,s=t(`<style>\n :host {\n display: inline-flex;\n --size: ${n}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,{ALLOWED_TAGS:["style"],FORCE_BODY:!0}),r=t(void 0!==this.svgContent?this.svgContent:`<svg viewBox="0 0 ${n} ${n}"></svg>`,{USE_PROFILES:{svg:!0,svgFilters:!0}});this.shadowRoot.innerHTML=s+r}update(){var e=this;this.waitUntilVisible().then(async function(){var t;const{name:n}=e.props,s=null!=(t=p.get(n))?t:u;e.svgContent=await s(n),e.render()})}waitUntilVisible(){return new Promise(e=>{this.observer=new IntersectionObserver(([t])=>{var n;t.isIntersecting&&(null==(n=this.observer)||n.disconnect(),this.observer=void 0,e())},{rootMargin:"50px"}),this.observer.observe(this)})}}m.tagName="pixiv-icon",a||window.customElements.get(m.tagName)||(window.PixivIcon=m,window.customElements.define(m.tagName,m));export{m as PixivIcon,r as PixivIconLoadError};
|
|
15
2
|
//# sourceMappingURL=index.modern.js.map
|
package/dist/index.modern.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.modern.js","sources":["../src/loaders.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","import { html, render } from 'lit-html'\nimport { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'\nimport type React from 'react'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n return render(\n html`\n <style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n </style>\n ${this.svgContent !== undefined\n ? unsafeSVG(this.svgContent)\n : html`<svg viewBox=\"0 0 ${size} ${size}\"></svg>`}\n `,\n this.shadowRoot!\n )\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\n// TODO: HMR対応\nif (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n}\n"],"names":["cache","Map","PixivIconLoadError","Error","constructor","message","super","Object","setPrototypeOf","this","createLoader","getPath","attributeName","has","get","rawSvg","then","path","fetch","response","ok","text","set","loaders","Promise","resolve","async","size","name","split","default","filename","encodeURIComponent","loadFromFile","loadFromRawUrl","defaultLoaders","attributes","PixivIcon","HTMLElement","static","map","entries","forEach","url","includes","TypeError","observedAttributes","props","partial","fromEntries","attribute","getAttribute","forceResizedSize","scale","Number","scaledSize","svgContent","observer","attachShadow","mode","connectedCallback","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","html","unsafeSVG","shadowRoot","waitUntilVisible","_this","loader","IntersectionObserver","first","isIntersecting","rootMargin","observe","tagName","window","customElements","define"],"mappings":"0TAAA,MAAMA,EAAQ,IAAIC,UAQLC,UAA2BC,MACtCC,YAAYC,GACVC,MAAMD,GACNE,OAAOC,eAAeC,kBAI1B,SAASC,EAAaC,GACpB,sBAAmCC,GACjC,GAAIZ,EAAMa,IAAID,GACZ,OAAOZ,EAAMc,IAAIF,GAGnB,MAAMG,QAAeJ,EAAQC,GAC1BI,KAAMC,GAASC,MAAMD,IACrBD,KAAMG,IACL,IAAKA,EAASC,GACZ,UAAUlB,uCAC6BU,OAIzC,OAAOO,EAASE,SAKpB,OAFArB,EAAMsB,IAAIV,EAAeG,GAElBA,GAMX,MAcaQ,EAAU,gBAdQb,EAAcE,GAC3CY,QAAQC,QAAQb,iBAGWF,EAAagB,MAAAA,IACxC,MAAOC,EAAMC,GAAQhB,EAAciB,MAAM,MAEjCC,QAASC,0BACLC,mBAAmBL,MAASK,mBAAmBJ,UAG3D,OAAOG,oBC/CT,MAAME,aAAEA,EAAFC,eAAgBA,GAAmBC,EAEnCC,EAAa,CAAC,OAAQ,QAAS,8BAoB/Bb,EAAU,IAAItB,UAOPoC,UAAkBC,YAGhBC,cACXC,GAIAjC,OAAOkC,QAAQD,GAAKE,QAAQ,EAAEd,EAAMe,MAClC,IAAKf,EAAKgB,SAAS,KACjB,UAAUC,aACLjB,wEAIPL,EAAQD,IAAIM,EAAM,WAChB,OAAOM,EAAeS,OAKjBG,gCACT,OAAOV,EAMLW,YACF,MAAMC,EAAUzC,OAAO0C,YACrBb,EAAWI,IAAKU,GAAc,CAACA,EAAWzC,KAAK0C,aAAaD,MAGxDtB,EAAOoB,EAAQpB,KAErB,GAAa,OAATA,EACF,UAAUiB,UAAU,gCAGtB,IAAKjB,EAAKgB,SAAS,KACjB,UAAUC,aACLjB,wEAIP,YACKoB,GACHpB,KAAAA,IAIAwB,uBACF,GAAiD,OAA7C3C,KAAKsC,MAAM,8BACb,YAGF,MAAOpB,GAAQlB,KAAKsC,MAAMnB,KAAKC,MAAM,KAC/BwB,EAAQC,OAAO7C,KAAKsC,MAAM,+BAEhC,MACO,WADCpB,KAEQ0B,EAILC,OAAO3B,GAAQ0B,EAKxBE,uBACF,MAAO5B,GAAQlB,KAAKsC,MAAMnB,KAAKC,MAAM,KAE/BwB,EAAQC,gBAAO7C,KAAKsC,MAAMM,SAAS,KAEzC,OAAQ1B,GACN,IAAK,SACH,WAAQ0B,QAWV,IAAK,KACH,OAAOC,OAAO3B,GAAQ0B,EAGxB,QACE,OAAOC,OAAO3B,IAKpBvB,cACEE,aA1EMkD,uBACAC,gBA0ENhD,KAAKiD,aAAa,CAAEC,KAAM,SAG5BC,oBACEnD,KAAKoD,SACLpD,KAAKqD,SAGPC,2CACON,aAAUO,aACfvD,KAAKgD,cAAWQ,EAGlBC,2BACEzD,KAAKqD,SAGPD,eACE,MAAMlC,WAAOlB,KAAK2C,oBAAoB3C,KAAK8C,WAE3C,OAAOM,EACLM;;;;sBADW;;;;;;;;UAAA;SAKKxC,OAQQsC,IAApBxD,KAAK+C,WACHY,EAAU3D,KAAK+C,YACfW,8BAFF,KAAA,aAE2BxC,EAAQA,IAEvClB,KAAK4D,YAIDP,yBACIQ,mBAAmBtD,KAAKU,uBAChC,MAAME,KAAEA,GAAS2C,EAAKxB,MAChByB,WAASjD,EAAQT,IAAIc,MAASK,EAEpCsC,EAAKf,iBAAmBgB,EAAO5C,GAC/B2C,EAAKV,WAIDS,mBACN,WAAW9C,QAAeC,IACxBhB,KAAKgD,SAAW,IAAIgB,qBAClB,EAAEC,YACIA,EAAMC,+BACHlB,aAAUO,aACfvD,KAAKgD,cAAWQ,EAChBxC,MAGJ,CAAEmD,oBAGJnE,KAAKgD,SAASoB,QAAQpE,SApKf4B,EACKyC,QAAU,aCjBvBC,OAAOC,eAAelE,IAAIuB,EAAUyC,WACvCC,OAAO1C,UAAYA,EACnB0C,OAAOC,eAAeC,OAAO5C,EAAUyC,QAASzC"}
|
|
1
|
+
{"version":3,"file":"index.modern.js","sources":["../src/loaders.ts","../src/ssr.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n/**\n * NOTICE: SSR 環境では `extends HTMLElement` できない\n *\n * @see https://github.com/vuejs/core/blob/9c304bfe7942a20264235865b4bb5f6e53fdee0d/packages/runtime-dom/src/apiCustomElement.ts#L143-L145\n */\nexport const BaseElement = (\n !__SERVER__ && CAN_USE_DOM ? HTMLElement : class {}\n) as typeof HTMLElement\n","import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nimport { BaseElement, __SERVER__ } from './ssr'\nimport { sanitize } from 'dompurify'\n\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends BaseElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n"],"names":["cache","Map","PixivIconLoadError","Error","constructor","message","super","Object","setPrototypeOf","this","createLoader","getPath","attributeName","has","get","rawSvg","then","path","fetch","response","ok","text","set","loaders","Promise","resolve","async","size","name","split","default","filename","encodeURIComponent","__SERVER__","window","CAN_USE_DOM","HTMLElement","BaseElement","loadFromFile","loadFromRawUrl","defaultLoaders","attributes","PixivIcon","static","map","warning","entries","forEach","url","includes","TypeError","observedAttributes","props","partial","fromEntries","attribute","getAttribute","forceResizedSize","scale","Number","scaledSize","svgContent","observer","attachShadow","mode","connectedCallback","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","style","sanitize","ALLOWED_TAGS","FORCE_BODY","svg","USE_PROFILES","svgFilters","shadowRoot","innerHTML","waitUntilVisible","_this","loader","IntersectionObserver","first","isIntersecting","rootMargin","observe","tagName","customElements","define"],"mappings":"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"}
|
package/dist/index.module.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"warning";import{sanitize as t}from"dompurify";function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function r(){return r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},r.apply(this,arguments)}function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,u(e,t)}function i(e){return i=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},i(e)}function u(e,t){return u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},u(e,t)}function c(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function s(e,t,n){return s=c()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&u(o,n.prototype),o},s.apply(null,arguments)}function a(e){var t="function"==typeof Map?new Map:void 0;return a=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return s(e,arguments,i(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),u(n,e)},a(e)}var l=new Map,f=/*#__PURE__*/function(e){function t(n){var r;return r=e.call(this,n)||this,Object.setPrototypeOf(function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(r),this instanceof t?this.constructor:void 0),r}return o(t,e),t}(/*#__PURE__*/a(Error));function p(e){return function(t){try{return l.has(t)?Promise.resolve(l.get(t)):Promise.resolve(e(t).then(function(e){return fetch(e)}).then(function(e){if(!e.ok)throw new f('Failed to fetch <pixiv-icon name="'+t+'">');return e.text()})).then(function(e){return l.set(t,e),e})}catch(e){return Promise.reject(e)}}}var v={loadFromRawUrl:p(function(e){return Promise.resolve(e)}),loadFromFile:p(function(e){try{var t=e.split("/"),n=t[1];return Promise.resolve(import("../svg/"+encodeURIComponent(t[0])+"/"+encodeURIComponent(n)+".svg")).then(function(e){return e.default})}catch(e){return Promise.reject(e)}})},d="undefined"==typeof window,h="undefined"!=typeof HTMLElement,m=!d&&h?HTMLElement:/*#__PURE__*/function(){return function(){}}(),b=v.loadFromFile,y=v.loadFromRawUrl,g=["name","scale","unsafe-non-guideline-scale"],w=new Map,O=/*#__PURE__*/function(i){function u(){var e;return(e=i.call(this)||this).svgContent=void 0,e.observer=void 0,e.attachShadow({mode:"open"}),e}o(u,i),u.extend=function(t){e(!d,"Using `PixivIcon.extend()` on server has no effect"),d||Object.entries(t).forEach(function(e){var t=e[0],n=e[1];if(!t.includes("/"))throw new TypeError(t+' is not a valid icon name. "name" must be named like [size]/[Name].');w.set(t,function(){return y(n)})})};var c,s,a,l=u.prototype;return l.connectedCallback=function(){this.render(),this.update()},l.disconnectedCallback=function(){var e;null==(e=this.observer)||e.disconnect(),this.observer=void 0},l.attributeChangedCallback=function(){this.update()},l.render=function(){var e,n=null!=(e=this.forceResizedSize)?e:this.scaledSize,r=t("<style>\n :host {\n display: inline-flex;\n --size: "+n+"px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>",{ALLOWED_TAGS:["style"],FORCE_BODY:!0}),o=t(void 0!==this.svgContent?this.svgContent:'<svg viewBox="0 0 '+n+" "+n+'"></svg>',{USE_PROFILES:{svg:!0,svgFilters:!0}});this.shadowRoot.innerHTML=r+o},l.update=function(){var e=this;this.waitUntilVisible().then(function(){try{var t,n=e.props.name,r=null!=(t=w.get(n))?t:b;return Promise.resolve(r(n)).then(function(t){e.svgContent=t,e.render()})}catch(e){return Promise.reject(e)}})},l.waitUntilVisible=function(){var e=this;return new Promise(function(t){e.observer=new IntersectionObserver(function(n){var r;n[0].isIntersecting&&(null==(r=e.observer)||r.disconnect(),e.observer=void 0,t())},{rootMargin:"50px"}),e.observer.observe(e)})},c=u,a=[{key:"observedAttributes",get:function(){return g}}],(s=[{key:"props",get:function(){var e=this,t=Object.fromEntries(g.map(function(t){return[t,e.getAttribute(t)]})),n=t.name;if(null===n)throw new TypeError('property "name" is required.');if(!n.includes("/"))throw new TypeError(n+' is not a valid icon name. "name" must be named like [size]/[Name].');return r({},t,{name:n})}},{key:"forceResizedSize",get:function(){if(null===this.props["unsafe-non-guideline-scale"])return null;var e=this.props.name.split("/")[0],t=Number(this.props["unsafe-non-guideline-scale"]);return"Inline"===e?16*t:Number(e)*t}},{key:"scaledSize",get:function(){var e,t=this.props.name.split("/")[0],n=Number(null!=(e=this.props.scale)?e:"1");switch(t){case"Inline":return 2===n?32:16;case"24":return Number(t)*n;default:return Number(t)}}}])&&n(c.prototype,s),a&&n(c,a),Object.defineProperty(c,"prototype",{writable:!1}),u}(m);O.tagName="pixiv-icon",d||window.customElements.get(O.tagName)||(window.PixivIcon=O,window.customElements.define(O.tagName,O));export{O as PixivIcon,f as PixivIconLoadError};
|
|
2
2
|
//# sourceMappingURL=index.module.js.map
|
package/dist/index.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.module.js","sources":["../src/loaders.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","import { html, render } from 'lit-html'\nimport { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'\nimport type React from 'react'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n return render(\n html`\n <style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n </style>\n ${this.svgContent !== undefined\n ? unsafeSVG(this.svgContent)\n : html`<svg viewBox=\"0 0 ${size} ${size}\"></svg>`}\n `,\n this.shadowRoot!\n )\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\n// TODO: HMR対応\nif (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n}\n"],"names":["cache","Map","PixivIconLoadError","message","_this","Object","setPrototypeOf","Error","createLoader","getPath","attributeName","has","get","then","path","fetch","response","ok","text","rawSvg","set","loaders","loadFromRawUrl","Promise","resolve","loadFromFile","split","name","import","encodeURIComponent","defaultLoaders","attributes","PixivIcon","svgContent","observer","attachShadow","mode","extend","map","entries","forEach","url","includes","TypeError","connectedCallback","this","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","size","forceResizedSize","scaledSize","html","unsafeSVG","shadowRoot","waitUntilVisible","_this2","props","loader","_this3","IntersectionObserver","isIntersecting","rootMargin","ROOT_MARGIN","observe","partial","fromEntries","attribute","_this4","getAttribute","scale","Number","HTMLElement","tagName","window","customElements","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.module.js","sources":["../src/loaders.ts","../src/ssr.ts","../src/PixivIcon.ts","../src/index.ts"],"sourcesContent":["const cache = new Map<string, string>()\n\ninterface SvgModule {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n __esModule: true\n default: string\n}\n\nexport class PixivIconLoadError extends Error {\n constructor(message?: string) {\n super(message)\n Object.setPrototypeOf(this, new.target)\n }\n}\n\nfunction createLoader(getPath: (attributeName: string) => Promise<string>) {\n return async function getSvgString(attributeName: string): Promise<string> {\n if (cache.has(attributeName)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return cache.get(attributeName)!\n }\n\n const rawSvg = await getPath(attributeName)\n .then((path) => fetch(path))\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(\n `Failed to fetch <pixiv-icon name=\"${attributeName}\">`\n )\n }\n\n return response.text()\n })\n\n cache.set(attributeName, rawSvg)\n\n return rawSvg\n }\n}\n\nexport type Loader = ReturnType<typeof createLoader>\n\nconst loadFromRawUrl: Loader = createLoader((attributeName) =>\n Promise.resolve(attributeName)\n)\n\nconst loadFromFile: Loader = createLoader(async (attributeName) => {\n const [size, name] = attributeName.split('/')\n\n const { default: filename } = (await import(\n `../svg/${encodeURIComponent(size)}/${encodeURIComponent(name)}.svg`\n )) as SvgModule\n\n return filename\n})\n\nexport const loaders = { loadFromRawUrl, loadFromFile }\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n/**\n * NOTICE: SSR 環境では `extends HTMLElement` できない\n *\n * @see https://github.com/vuejs/core/blob/9c304bfe7942a20264235865b4bb5f6e53fdee0d/packages/runtime-dom/src/apiCustomElement.ts#L143-L145\n */\nexport const BaseElement = (\n !__SERVER__ && CAN_USE_DOM ? HTMLElement : class {}\n) as typeof HTMLElement\n","import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './filenames'\nimport { loaders as defaultLoaders, Loader } from './loaders'\nimport { BaseElement, __SERVER__ } from './ssr'\nimport { sanitize } from 'dompurify'\n\nconst { loadFromFile, loadFromRawUrl } = defaultLoaders\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\nconst loaders = new Map<string, Loader>()\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends BaseElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, url]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n loaders.set(name, function customLoader() {\n return loadFromRawUrl(url)\n })\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<typeof attributes[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n connectedCallback() {\n this.render()\n this.update()\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n }\n\n attributeChangedCallback() {\n this.update()\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private update() {\n void this.waitUntilVisible().then(async () => {\n const { name } = this.props\n const loader = loaders.get(name) ?? loadFromFile\n\n this.svgContent = await loader(name)\n this.render()\n })\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { PixivIconLoadError } from './loaders'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n"],"names":["cache","Map","PixivIconLoadError","message","_this","Object","setPrototypeOf","Error","createLoader","getPath","attributeName","has","get","then","path","fetch","response","ok","text","rawSvg","set","loaders","loadFromRawUrl","Promise","resolve","loadFromFile","split","name","import","encodeURIComponent","__SERVER__","window","CAN_USE_DOM","HTMLElement","BaseElement","defaultLoaders","attributes","PixivIcon","svgContent","observer","attachShadow","mode","extend","map","warning","entries","forEach","url","includes","TypeError","connectedCallback","this","render","update","disconnectedCallback","disconnect","undefined","attributeChangedCallback","size","forceResizedSize","scaledSize","style","sanitize","ALLOWED_TAGS","FORCE_BODY","svg","USE_PROFILES","svgFilters","shadowRoot","innerHTML","waitUntilVisible","_this2","props","loader","_this3","IntersectionObserver","isIntersecting","rootMargin","ROOT_MARGIN","observe","partial","fromEntries","attribute","_this4","getAttribute","scale","Number","tagName","customElements","define"],"mappings":"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"}
|
package/dist/loaders.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaders.d.ts","sourceRoot":"","sources":["../src/loaders.ts"],"names":[],"mappings":"AAQA,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,CAAC,EAAE,MAAM;CAI7B;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,mBACrB,MAAM,KAAG,QAAQ,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"loaders.d.ts","sourceRoot":"","sources":["../src/loaders.ts"],"names":[],"mappings":"AAQA,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,CAAC,EAAE,MAAM;CAI7B;AAED,iBAAS,YAAY,CAAC,OAAO,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,mBACrB,MAAM,KAAG,QAAQ,MAAM,CAAC,CAsB3E;AAED,oBAAY,MAAM,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;AAgBpD,eAAO,MAAM,OAAO;oCAxCgC,MAAM,KAAG,QAAQ,MAAM,CAAC;kCAAxB,MAAM,KAAG,QAAQ,MAAM,CAAC;CAwCrB,CAAA"}
|
package/dist/ssr.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const __SERVER__: boolean;
|
|
2
|
+
/**
|
|
3
|
+
* NOTICE: SSR 環境では `extends HTMLElement` できない
|
|
4
|
+
*
|
|
5
|
+
* @see https://github.com/vuejs/core/blob/9c304bfe7942a20264235865b4bb5f6e53fdee0d/packages/runtime-dom/src/apiCustomElement.ts#L143-L145
|
|
6
|
+
*/
|
|
7
|
+
export declare const BaseElement: {
|
|
8
|
+
new (): HTMLElement;
|
|
9
|
+
prototype: HTMLElement;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=ssr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,SAAgC,CAAA;AAIvD;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;CAED,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charcoal-ui/icons",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-alpha.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"source": "./src/index.ts",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"clean": "rimraf dist"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
+
"@types/dompurify": "^2.3.3",
|
|
21
22
|
"@types/jest": "^27.4.0",
|
|
22
23
|
"@types/react": "^17.0.38",
|
|
23
24
|
"microbundle": "^0.14.2",
|
|
@@ -27,7 +28,8 @@
|
|
|
27
28
|
"typescript": "^4.5.5"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"
|
|
31
|
+
"dompurify": "^2.3.6",
|
|
32
|
+
"warning": "^4.0.3"
|
|
31
33
|
},
|
|
32
34
|
"files": [
|
|
33
35
|
"src",
|
|
@@ -37,5 +39,10 @@
|
|
|
37
39
|
"publishConfig": {
|
|
38
40
|
"access": "public"
|
|
39
41
|
},
|
|
40
|
-
"
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/pixiv/charcoal.git",
|
|
45
|
+
"directory": "packages/icons"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "f68b0533a24b68f4726711fd2f5fb23be1ccba93"
|
|
41
48
|
}
|
package/src/PixivIcon.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { html, render } from 'lit-html'
|
|
2
|
-
import { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'
|
|
3
1
|
import type React from 'react'
|
|
2
|
+
import warning from 'warning'
|
|
4
3
|
import { KnownIconFile } from './filenames'
|
|
5
4
|
import { loaders as defaultLoaders, Loader } from './loaders'
|
|
5
|
+
import { BaseElement, __SERVER__ } from './ssr'
|
|
6
|
+
import { sanitize } from 'dompurify'
|
|
7
|
+
|
|
6
8
|
const { loadFromFile, loadFromRawUrl } = defaultLoaders
|
|
7
9
|
|
|
8
10
|
const attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const
|
|
@@ -32,7 +34,7 @@ type Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがn
|
|
|
32
34
|
? false
|
|
33
35
|
: true
|
|
34
36
|
|
|
35
|
-
export class PixivIcon extends
|
|
37
|
+
export class PixivIcon extends BaseElement {
|
|
36
38
|
static readonly tagName = 'pixiv-icon'
|
|
37
39
|
|
|
38
40
|
static extend(
|
|
@@ -40,6 +42,11 @@ export class PixivIcon extends HTMLElement {
|
|
|
40
42
|
? Record<ExtendedIconFile, string>
|
|
41
43
|
: Record<string, string>
|
|
42
44
|
) {
|
|
45
|
+
warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')
|
|
46
|
+
if (__SERVER__) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
Object.entries(map).forEach(([name, url]) => {
|
|
44
51
|
if (!name.includes('/')) {
|
|
45
52
|
throw new TypeError(
|
|
@@ -152,25 +159,30 @@ export class PixivIcon extends HTMLElement {
|
|
|
152
159
|
render() {
|
|
153
160
|
const size = this.forceResizedSize ?? this.scaledSize
|
|
154
161
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
+
const style = sanitize(
|
|
163
|
+
`<style>
|
|
164
|
+
:host {
|
|
165
|
+
display: inline-flex;
|
|
166
|
+
--size: ${size}px;
|
|
167
|
+
}
|
|
162
168
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
? unsafeSVG(this.svgContent)
|
|
170
|
-
: html`<svg viewBox="0 0 ${size} ${size}"></svg>`}
|
|
171
|
-
`,
|
|
172
|
-
this.shadowRoot!
|
|
169
|
+
svg {
|
|
170
|
+
width: var(--size);
|
|
171
|
+
height: var(--size);
|
|
172
|
+
}
|
|
173
|
+
</style>`,
|
|
174
|
+
{ ALLOWED_TAGS: ['style'], FORCE_BODY: true }
|
|
173
175
|
)
|
|
176
|
+
|
|
177
|
+
const svg = sanitize(
|
|
178
|
+
this.svgContent !== undefined
|
|
179
|
+
? this.svgContent
|
|
180
|
+
: `<svg viewBox="0 0 ${size} ${size}"></svg>`,
|
|
181
|
+
{ USE_PROFILES: { svg: true, svgFilters: true } }
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
185
|
+
this.shadowRoot!.innerHTML = style + svg
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
private update() {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PixivIcon, Props } from './PixivIcon'
|
|
2
|
+
import { __SERVER__ } from './ssr'
|
|
2
3
|
export { PixivIcon, type KnownIconType, type Props } from './PixivIcon'
|
|
3
4
|
export { PixivIconLoadError } from './loaders'
|
|
4
5
|
|
|
@@ -15,8 +16,10 @@ declare global {
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
window.PixivIcon
|
|
21
|
-
|
|
19
|
+
if (!__SERVER__) {
|
|
20
|
+
// TODO: HMR対応
|
|
21
|
+
if (!window.customElements.get(PixivIcon.tagName)) {
|
|
22
|
+
window.PixivIcon = PixivIcon
|
|
23
|
+
window.customElements.define(PixivIcon.tagName, PixivIcon)
|
|
24
|
+
}
|
|
22
25
|
}
|
package/src/loaders.ts
CHANGED
|
@@ -16,6 +16,7 @@ export class PixivIconLoadError extends Error {
|
|
|
16
16
|
function createLoader(getPath: (attributeName: string) => Promise<string>) {
|
|
17
17
|
return async function getSvgString(attributeName: string): Promise<string> {
|
|
18
18
|
if (cache.has(attributeName)) {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
19
20
|
return cache.get(attributeName)!
|
|
20
21
|
}
|
|
21
22
|
|
package/src/ssr.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const __SERVER__ = typeof window === 'undefined'
|
|
2
|
+
|
|
3
|
+
const CAN_USE_DOM = typeof HTMLElement !== 'undefined'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* NOTICE: SSR 環境では `extends HTMLElement` できない
|
|
7
|
+
*
|
|
8
|
+
* @see https://github.com/vuejs/core/blob/9c304bfe7942a20264235865b4bb5f6e53fdee0d/packages/runtime-dom/src/apiCustomElement.ts#L143-L145
|
|
9
|
+
*/
|
|
10
|
+
export const BaseElement = (
|
|
11
|
+
!__SERVER__ && CAN_USE_DOM ? HTMLElement : class {}
|
|
12
|
+
) as typeof HTMLElement
|