Feat v4 (#6329)
* refactor(icon): remove style dir (#6215) * refactor: rename locale * refactor: locale-provider * refactor: modal * refactor: menu * fix: custom class (#6217) * refactor: tooltip * refactor: grid (#6220) * refactor: grid * fix(grid): align & justify responsive * chore: update demo and snapshot * fix: row ts type not work * doc: update demo * refactor: ts * refactor: spin (#6222) * fix: typo (#6218) * fix: typo * docs<upload>: docs update * refactor: spin * refactor: spin * refactor: spin * refactor: spinnn * refactor: spin --------- Co-authored-by: lyn <76365499@qq.com> * fix: spin error #6222 * test: test case error (#6225) * fix: inject value maybe undefined * fix: tootip emit correct value * fix: rollback warning suffix avoid test break * doc(grid): remove unused type="flex" * refactor: skeleton (#6224) * refactor: skeleton * refactor: skeleton style * chore: modify skeleton demo style * fix(button): link and text should not have wave (#6226) * refactor: dropdown * refactor: popover & popconfirm * refactor(tag): less to cssinjs (#6227) * refactor(empty): less to cssinjs (#6230) * refactor(empty): less to cssinjs * chore: remove unuse code * fix: reactivity lose * fix: empty props #6230 * refactor: progress style (#6234) * refactor: progress * refactor: progress style * fix: progress attrs * refactor: progress #6234 * refactor: switch (#6236) * refactor: switch style * refactor: delete switch style * refactor:input (#6237) * refactor:input * fix inheritAttrs:false * fix attrs.class * feat: input add disabled * refactor:comment (#6238) * refactor:comment * fix inheritAttrs: false & attrs.class * refactor:pageheader (#6239) * refactor:pageheader * fix inheritAttrs: false & attrs.class * refactor:statistic (#6240) * refactor:statistic * fix inheritAttrs: false & attrs.class * refactor:list (#6241) * refactor:list * fix inheritAttrs: false & attrs.class * feat: update type * refactor(Space): less to cssinjs & add compact mode (#6229) * refactor(Space): less to cssinjs & add compact mode * chore(space): update md * chore(space): add demo * chore(space): add some demo * feat(button): add compact mode * fix: reactivity lose * docs: fix props version --------- Co-authored-by: tangjinzhou <415800467@qq.com> * perf: space compact * refactor:typography (#6244) * refactor:typography * fix return * fix import type * fix: typography #6244 * refactor:datepicker (#6245) * refactor: datepicker type * refactor: rate style (#6254) * refactor(layout): less to cssinjs (#6249) * doc: update layout cover * refactor(result): less to cssinjs (#6246) * refactor(result): less to cssinjs * fix: class name is overridden * docs: update result cover * refactor:slider (#6250) * feat: slider deprecated tooltipVisible * refactor(crad): less to cssinjs (#6258) * update * switch * Style adjustment * refactor(Card): less to cssinjs * Eliminate invalid code * optimization and adjustment css * Adjust the css * Optimize each item * adjustment css * refactor: card #6258 * refactor:carousel (#6262) * refactor:carousel * docs:update & refactor: carousel type --------- Co-authored-by: tangjinzhou <415800467@qq.com> * refactor:transfer (#6247) * refactor:transfer * merge v4 branch & fix theme interface conflict * docs:update & refactor: transfer type * perf: transfer * refactor:checkbox (#6248) * refactor:checkbox * docs:update & refactor: checkbox type * feat: checkbox add disabled context * refactor:pagination (#6251) * refactor:pagination * docs:update & refactor: pagination type * style: update pagination props type * refactor: mentions (#6255) * refactor: mentions * refactor: mentions menu provider * doc: update mentions demo * refcator:upload (#6261) * refcator:upload * docs:update & refactor: upload type * Update style.ts --------- Co-authored-by: tangjinzhou <415800467@qq.com> * perf: upload motion * refactor:timeline (#6263) * refactor:timeline * docs:update & refactor: timeline type * perf: timeline * refactor:steps (#6264) * refactor:steps * fix ...attrs * fix StepsToken error * docs:update & refactor: steps type * fix: steps icon clss error * refactor:collapse (#6266) * refactor:collapse * fix collapse props version * docs:update & refactor: collapse type & fix collapsible * feat: update collapse type * refactor:inputnumber (#6265) * refactor:inputnumber * docs:update & refactor: inputnumber type --------- Co-authored-by: tangjinzhou <415800467@qq.com> * feat: number add compactSize & disabledContext * refactor:table (#6267) * refactor:table * docs:update & refactor: table type --------- Co-authored-by: tangjinzhou <415800467@qq.com> * refactor: table * feat: table add expandColumnTitle slot * refactor:calendar (#6269) * refactor:calendar * docs:update * refactor:timepicker (#6270) * refactor:timepicker * docs:update & refactor: timepicker type * refactor:tree (#6276) * Feat v4 fix type errors (#6285) * fix compile type errors * fix menuprops type import * fix lint errors * fix lint errors * fix format error * fix node version * fix run dist error * fix run lint * fix as any * fix string type * refactor: rename locale file * feat: tree add leafIcon * [tabs] :less to cssinjs (#6288) * update * switch * Style adjustment * refactor(Card): less to cssinjs * tabs: less to cssinjs 开发ing * add function cssinjs * Eliminate irrelevant code * Eliminate irrelevant code 2 * update components * Eliminate irrelevant input code * refactor: tabs #6288 * feat: add segmented (#6286) * refactor: segmented #6286 * refactor:select (#6295) * refactor:select * update doc * delete useless * feat: select add context size * refactor: tree select (#6296) * feat: tree-select add context size * perf: table * docs: update doc toc * refactor: cascader * refactor: auto-complete * refactor: image * refactor: drawer * refactor:radio (#6299) * refactor:radio * fix attrs * feat: radio add disabled context * fix: some type & doc (#6292) * fix: typo (#6218) * fix: typo * docs<upload>: docs update * fix: type of minute in props disabledDateTime of DatePicker (#6233) * docs: typo (#6256) * feat: tooltip added overlayInnerStyle attribute * Update abstractTooltipProps.ts * Update Tooltip.tsx --------- Co-authored-by: lyn <76365499@qq.com> Co-authored-by: H1mple <35363759+baohangxing@users.noreply.github.com> Co-authored-by: tangjinzhou <415800467@qq.com> * refactor: form * fix: directive not work * fix: use open, remove visible * doc: update cover * refactor: remove not use code * chore: update build script * doc: update doc * doc: refactor doc * chore: update token error * chore: update style * refactor: rename _style to style * fix: tag warning * fix(dropdown): open invalid (#6316) * feat: add watermark (#6300) * feat: add watermark * feat: add watermark demo * feat: add mutationObserver * feat: add watermark demo * refactor: watermark type * doc: add theme-editor * fix: inject value maybe undefined && tag style invalid (#6320) * fix: inject value maybe undefined * fix(tag): style invalid * feat: add qrcode (#6315) * feat: add qrcode * fix: qrcode bug * fix: qrcode value required * refactor: props deconstruct * Feat v4 floatbutton (#6294) * feat: add float-button components * fix type & demo display * fix components entry * fix review bug * fix bug * fix .value * refactor: qrcode #6315 * refactor: float-button * fix: groupsize context error * fix: floatbutton animation not work * Feat v4 theme editor (#6348) * feat: add theme editor container * feat: add theme editor layout * add left panel * add vue-colorful & fix bug * 修复hue组件抖动问题 * fix bug && add demo * fix bug * fix demo preview * fix theme editor components demo * fix: token effect error * Feat v4 theme editor (#6349) * feat: add theme editor container * feat: add theme editor layout * add left panel * add vue-colorful & fix bug * 修复hue组件抖动问题 * fix bug && add demo * fix bug * fix demo preview * fix theme editor components demo * add theme editor token drawer * add theme editor token drawer * fix bug * open commment * fix error demo * fix theme editor bug * fix: cssinjs effect error * doc: format code * fix: tag click event not trigger * release 4.0.0-alpha.1 * fix: qrcode type * fix: remove not use file * doc: update doc site * doc: update site * doc: fix theme editor bgcolor (#6358) * fix: motion not work * release 4.0.0-alpha.2 * fix: qrcode ; error, close #6362 * fix docs dark theme & add docs coverDark (#6367) * fix docs dark theme & add docs coverDark * fix theme Editor edit * fix: dropdown divider disappear, close #6365 (#6369) * doc: update baner * fix: button wave not work * fix: ant-piker-cell-range-hover-end style error (#6373) * fix: ant-piker-cell-range-hover-end style error * feat: be consistent with antd * feat: be consistent with antd * fix: ConfigProvider error for style, close #6368 * release 4.0.0-alpha.4 * style: add dark style for `pre` and `code` (#6382) * docs: version menu (#6390) * Feat(DatePicker): increase presets prop (#6387) * feat(date-picker): add PresetDate type * feat(date-picker): add usePresets hook * feat(date-picker): add PresetPanel Component * feat(date-picker): add PresetPanel Component * feat(demo): update Preset Ranges Examples * feat(docs): add new prop presets * feat(docs): add new prop presets with english * fix(RangePicker): footer is not managed by panels * chore(Picker): prefixCls default rc-picker * chore(date-picker): update presetted-ranges demo * chore(date-picker): update rangePickerProps'presets * feat(date-picker): presets reactively processing * chore(date-picker): update type * refactor(RangePicker): deprecated ranges prop * chore(date-picker): update type * chore(PickerPanel): del notuse panelRef --------- Co-authored-by: tangjinzhou <415800467@qq.com> * fix: datepicker presets error #6387 * docs: update datepicker doc #6387 * feat(Steps): add items prop and variants (#6406) * refactor(steps): add items prop and variants * feat(steps): add Label Placement and Inline Steps demo * feat(steps): Label Placement and Inline Steps snap * test(steps): Steps demo snap * feat(Steps): update docs * fix(Step): progressDot * chore(useLegacyItems): change from warning to devWarning * refactor(Steps): Remove useLegacyItems * refactor(Steps): renderStep * test(Steps): update test snapshot * chore(Steps): filterEmpty * feat(Steps): update docs * docs: update site * refactor: steps #6406 * test: update steps * perf: shallowRef instead ref * fix(Modal): fix modal locale (#6423) * feat(StyleProvider): add StyleProvider handle cssinjs features (#6415) * feat(StyleProvider): StyleProvider * feat(StyleProvider): refactor to use context * chore(StyleProvider): update AStyleProviderProps type * chore(App): reback * chore(StyleProvider): export StyleProvider * feat(StyleProvider): update StyleProvider docs * feat(StyleProvider): update StyleProvider docs * feat(StyleProvider): add StyleProvider docs routes * chore(StyleProvider): with useStyleProvider * docs: update compatiple #6415 * feat(Progress): enhance size prop and add variants (#6409) * refactor(progress): Progress size and add variants * feat(progress): add `getsize` * refactor(progress): Progress size and add variants * chore(progress): update props type * chore(progress): update props type * feat(progress): update demo * feat(progress): update docs * test(progress): update test snap * fix(Circle): Merging classes * test(progress): update test snap * feat(progress): add size demo * test(progress): add size snapshot * chore(Progress): reback Circle svg class change * fix: progress borderRadius reactive #6409 * fix(defaultConfigProvider): add getPopupContainer (#6425), close #6419 * fix: qrcode size error, close #6418 * release 4.0.0-alpha.4 * fix: picker import error * test: add QRCode unit testing (#6441) * fix * fix compile type errors * fix menuprops type import * fix lint errors * fix lint errors * fix format error * fix node version * fix run dist error * fix run lint * fix as any * fix string type * fix steps error & fix docs version select option & fix theme editor error * fix(badge): badge props count default value error (#6433) * docs: update site responsive * fix: modal api method i18n not work, close #6438 * release 4.0.0-alpha.5 * chore(docs): update docs (#6446) * docs(space): update demo * docs(affix): update docs * fix: cssinjs compatibility (#6454) * feat: add convertLegacyToken * docs: v4 vuedocs (#6468) * fix introduce doc * fix getting-started doc * add migration-v4 doc * fix docs * Update migration-v4.zh-CN.md * Update migration-v4.zh-CN.md * Update migration-v4.en-US.md * Update migration-v4.zh-CN.md * Update getting-started.en-US.md * Update getting-started.zh-CN.md * Update introduce.en-US.md * Update introduce.zh-CN.md --------- Co-authored-by: tangjinzhou <415800467@qq.com> * feat: remove backtop * feat(anchor): add direction action (#6447) * refactor(anchor): direction show * refactor(anchor): update anchor css * feat(anchor): update demo * test(anchor): update demo test snap * feat(anchor): update docs * Update index.zh-CN.md * Update index.en-US.md --------- Co-authored-by: tangjinzhou <415800467@qq.com> * feat: anchor add customTitle slot #6447 * docs: update doc anchor * feat(menu): icon support function components with items and update demo (#6457) * fix(menu): icon do not show problem * fix(menu): icon do not show problem * feat(menu): update demo * test(menu): update demo snap * chore(Menu): update docs * test(Menu): update demo * Update MenuItem.tsx * Update SubMenu.tsx --------- Co-authored-by: tangjinzhou <415800467@qq.com> * doc: update menu icon * feat: menu items icon add arg * fix: antd.min error * release 4.0.0-alpha.6 * fix: table resizable not work && type error (#6514) * Refactor(demo): change options to composition api (#6499) * feat(demo): A-B * feat(demo): update B-checkbox * feat(demo): update CheckBox -DatePicker * feat(demo): update DatePicker - Form * feat(demo): update Form - List * feat(demo): update List-pagination * feat(demo): update List - skeleton * feat(demo): update skeleton - switch * feat(demo): update skeleton - switch * feat(demo): update switch - upload * feat(demo): update watermark * fix(demo): del hashId * fix: submenu type lose theme * fix: dropdown menu hide error * fix: dealing with switching topics modal, notification, message does not take effect close #6512 (#6518) * fix: resolve dark mode not support * fix: unified expression * feat(modal): add useModal (#6517) * feat(modal): add useModal hook * feat(modal): add HookModal demo * test(modal): update HookModal demo snap * feat(modal): update modal docs * chore(modal): update modal type * perf: useModal #6517 * release 4.0.0-beta.1 * docs: fix tab demo error * fix(config-provider): fix ConfigProvider.config is not function close #6528 (#6529) * Feat(use): add useMessage useNotification (#6527) * feat(Message): add useMessage hook * feat(Notification): add useNotification hook * feat(Message): add Hook demo * feat(Notification): add Hook demo * test(Message): update demo snap * test(Notification): update demo snap * docs(Message): update docs with FAQ * docs(Notification): update docs with FAQ * refactor: useMessage #6527 * refactor: useNotification #6527 * release 4.0.0-beta.2 * docs(button): update demo with space (#6536) * feat(button): demo space * test(button): update demo snap * chore(button): disabled demo Ghost space * test(button): update disabled demo snap * docs(introduce): update docs (#6539) * docs(introduce): update docs * docs(introduce): add Dollar * Update introduce.zh-CN.md * Update introduce.en-US.md --------- Co-authored-by: tangjinzhou <415800467@qq.com> * docs(customize-theme): update docs (#6540) * fix introduce doc * fix getting-started doc * add migration-v4 doc * fix docs * Update migration-v4.zh-CN.md * Update migration-v4.zh-CN.md * Update migration-v4.en-US.md * Update migration-v4.zh-CN.md * Update getting-started.en-US.md * Update getting-started.zh-CN.md * Update introduce.en-US.md * Update introduce.zh-CN.md * update customize-theme doc & fix migration-v4 error * update customize-theme doc * fix migration-v4 error * remove SSR & shadowDom * Update customize-theme.zh-CN.md * Update customize-theme.en-US.md --------- Co-authored-by: tangjinzhou <415800467@qq.com> * fix: getPopupContainer not work * release 4.0.0-beta.3 * release 4.0.0-beta.4 * docs: update grid docs (#6549) Co-authored-by: zhuzhengjian <zhuzhengjian@hoteamsoft.com> * test(alert): update demo with space (#6541) * docs(alert): update demo with space * docs(alert): update alert test snap --------- Co-authored-by: zhuzhengjian <zhuzhengjian@hoteamsoft.com> * fix: components bug & update docs (#6548) * fix bug * fix test case and update snapshot,fix space merge class * docs(grid): update migrate docs && delete xxxl in grid docs (#6562) * fix: segmentd disabled label is undefined (#6556) * fix: segmentd disabled label is undefined * fix: segmentd disabled label is undefined * fix: segmentd disabled label is undefined * fix(grid): remove grid xxxl attribute (#6572) * fix: remove grid xxxl attribute * docs: remove xxxl in grid docs * fix: tooltip custom color error * feat: remove Step __legacy * feat: add tour (#6332) * feat v4 add tour * fix type error * sync tour from antd5.4.6 & fix type error * fix error * refactor: tour #6332 * fix: tour center * fix: picker support v-show * test: update snap * test: update tour test * fix: tour-mask attrs pointer-events (#6577) * fix: tour animated * feat: support vue 3.3 slot type * release 4.0.0-rc.1 * release 4.0.0-rc.2, close #6588 * 4.0.0-rc.3 * chore: remove vue private api * fix: paginantion error, close #6590 * release 4.0.0-rc.4 * fix: checxbox style * fix: pagination mini size style * release 4.0.0-rc.5 * docs: update v4 tabs doc error(#6606) (#6607) * docs: add ant-design-vue nuxt module (#6620) * fix: layout-sider and menu transition style(#6637) (#6640) * docs: fixed the style error of online demo (#6630) * feat: ✨checkbox label slot support use option label (#6642) * docs: 📃change the default setting of "treeNodeFilterProp" from "value" to "label" * revert: ↩revert this config and create another pr to commit * feat: ✨checkbox label slot support use option label * test: 🧪update checkbox *.snap file --------- Co-authored-by: tangjinzhou <415800467@qq.com> * fix: add disabledContext override with form components (#6618) * fix: add disabledContext override with form components * test: update snap * fix: LabelWidth demo filename * fix: fontsize spelling mistake * fix(tour): target position (#6629) * style: format lint * docs(form): add form disabled demo (#6658) * fix: comment node error * release 4.0 * fix: portalWrapper add autoLock prop (#6687), close #6649 * fix: image animation & zindex, close #6675 * docs(QRCode): Synchronize QR code demonstration and add SVG (#6660) * fix: Synchronize QR code demonstration and add SVG * fix: responsive loss and invalid border style * docs: synchronize antd5.6.3 QRCode color in dark mode * feat: calendar select support info.source param (#6697) * docs: add ant-design-vue nuxt module * feat: calendar select support info.source param * docs: synchronous config-provider demo (#6706) * revert: #6706 * docs: export space-compact types (#6716) * release 4.0.0 --------- Co-authored-by: bqy_fe <1743369777@qq.com> Co-authored-by: zkwolf <chenhao5866@gmail.com> Co-authored-by: Zev Zhu <45655660+aibayanyu20@users.noreply.github.com> Co-authored-by: lyn <76365499@qq.com> Co-authored-by: 果冻橙 <shifeng199307@gmail.com> Co-authored-by: songsong0707 <74165917+songsong0707@users.noreply.github.com> Co-authored-by: yang <30883395+webvs2@users.noreply.github.com> Co-authored-by: selicens <1244620067@qq.com> Co-authored-by: 一堆菠萝 <53335668+JavanShen@users.noreply.github.com> Co-authored-by: H1mple <35363759+baohangxing@users.noreply.github.com> Co-authored-by: Cherry7 <79909910+CCherry07@users.noreply.github.com> Co-authored-by: Konv Suu <2583695112@qq.com> Co-authored-by: luoawai <32483950+luoawai@users.noreply.github.com> Co-authored-by: 鱼见 <657715602@qq.com> Co-authored-by: zhuzhengjian <zhuzhengjian@hoteamsoft.com> Co-authored-by: Cupid Valentine <53572196+valcosmos@users.noreply.github.com> Co-authored-by: 专业逮虾户aa <30494925+waldonUB@users.noreply.github.com> Co-authored-by: PanStar <PanStar@users.noreply.github.com>pull/6719/head 4.0.0
parent
a0e94978f5
commit
a2e50dc43e
|
@ -1,195 +1,36 @@
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const defaultVars = require('./scripts/default-vars');
|
|
||||||
const darkVars = require('./scripts/dark-vars');
|
|
||||||
const compactVars = require('./scripts/compact-vars');
|
|
||||||
|
|
||||||
function generateThemeFileContent(theme) {
|
const restCssPath = path.join(process.cwd(), 'components', 'style', 'reset.css');
|
||||||
return `const { ${theme}ThemeSingle } = require('./theme');\nconst defaultTheme = require('./default-theme');\n
|
const tokenStatisticPath = path.join(process.cwd(), 'components', 'version', 'token.json');
|
||||||
module.exports = {
|
const tokenMetaPath = path.join(process.cwd(), 'components', 'version', 'token-meta.json');
|
||||||
...defaultTheme,
|
|
||||||
...${theme}ThemeSingle
|
|
||||||
}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need compile additional content for antd user
|
|
||||||
function finalizeCompile() {
|
function finalizeCompile() {
|
||||||
|
if (fs.existsSync(path.join(__dirname, './es'))) {
|
||||||
|
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'es', 'style', 'reset.css'));
|
||||||
|
fs.copyFileSync(tokenStatisticPath, path.join(process.cwd(), 'es', 'version', 'token.json'));
|
||||||
|
fs.copyFileSync(tokenMetaPath, path.join(process.cwd(), 'es', 'version', 'token-meta.json'));
|
||||||
|
}
|
||||||
|
|
||||||
if (fs.existsSync(path.join(__dirname, './lib'))) {
|
if (fs.existsSync(path.join(__dirname, './lib'))) {
|
||||||
// Build a entry less file to dist/antd.less
|
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'lib', 'style', 'reset.css'));
|
||||||
const componentsPath = path.join(process.cwd(), 'components');
|
fs.copyFileSync(tokenStatisticPath, path.join(process.cwd(), 'lib', 'version', 'token.json'));
|
||||||
let componentsLessContent = '';
|
fs.copyFileSync(tokenMetaPath, path.join(process.cwd(), 'lib', 'version', 'token-meta.json'));
|
||||||
// Build components in one file: lib/style/components.less
|
|
||||||
fs.readdir(componentsPath, (err, files) => {
|
|
||||||
files.forEach(file => {
|
|
||||||
if (fs.existsSync(path.join(componentsPath, file, 'style', 'index.less'))) {
|
|
||||||
componentsLessContent += `@import "../${path.posix.join(
|
|
||||||
file,
|
|
||||||
'style',
|
|
||||||
'index-pure.less',
|
|
||||||
)}";\n`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'lib', 'style', 'components.less'),
|
|
||||||
componentsLessContent,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildThemeFile(theme, vars) {
|
|
||||||
// Build less entry file: dist/antd.${theme}.less
|
|
||||||
if (theme !== 'default') {
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', `antd.${theme}.less`),
|
|
||||||
`@import "../lib/style/${theme}.less";\n@import "../lib/style/components.less";`,
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(`Built a entry less file to dist/antd.${theme}.less`);
|
|
||||||
} else {
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', `default-theme.js`),
|
|
||||||
`module.exports = ${JSON.stringify(vars, null, 2)};\n`,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build ${theme}.js: dist/${theme}-theme.js, for less-loader
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', `theme.js`),
|
|
||||||
`const ${theme}ThemeSingle = ${JSON.stringify(vars, null, 2)};\n`,
|
|
||||||
{
|
|
||||||
flag: 'a',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', `${theme}-theme.js`),
|
|
||||||
generateThemeFileContent(theme),
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(`Built a ${theme} theme js file to dist/${theme}-theme.js`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function finalizeDist() {
|
function finalizeDist() {
|
||||||
if (fs.existsSync(path.join(__dirname, './dist'))) {
|
if (fs.existsSync(path.join(__dirname, './dist'))) {
|
||||||
// Build less entry file: dist/antd.less
|
fs.copyFileSync(restCssPath, path.join(process.cwd(), 'dist', 'reset.css'));
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', 'antd.less'),
|
|
||||||
'@import "../lib/style/default.less";\n@import "../lib/style/components.less";',
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', 'theme.js'),
|
|
||||||
`const defaultTheme = require('./default-theme.js');\n`,
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('Built a entry less file to dist/antd.less');
|
|
||||||
buildThemeFile('default', defaultVars);
|
|
||||||
buildThemeFile('dark', darkVars);
|
|
||||||
buildThemeFile('compact', compactVars);
|
|
||||||
buildThemeFile('variable', {});
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(process.cwd(), 'dist', `theme.js`),
|
|
||||||
`
|
|
||||||
function getThemeVariables(options = {}) {
|
|
||||||
let themeVar = {
|
|
||||||
'hack': \`true;@import "\${require.resolve('ant-design-vue/lib/style/color/colorPalette.less')}";\`,
|
|
||||||
...defaultTheme
|
|
||||||
};
|
|
||||||
if(options.dark) {
|
|
||||||
themeVar = {
|
|
||||||
...themeVar,
|
|
||||||
...darkThemeSingle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(options.compact){
|
|
||||||
themeVar = {
|
|
||||||
...themeVar,
|
|
||||||
...compactThemeSingle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return themeVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
darkThemeSingle,
|
|
||||||
compactThemeSingle,
|
|
||||||
getThemeVariables
|
|
||||||
}`,
|
|
||||||
{
|
|
||||||
flag: 'a',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isComponentStyleEntry(file) {
|
|
||||||
return file.path.match(/style(\/|\\)index\.tsx/);
|
|
||||||
}
|
|
||||||
|
|
||||||
function needTransformStyle(content) {
|
|
||||||
return content.includes('../../style/index.less') || content.includes('./index.less');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
compile: {
|
compile: {
|
||||||
includeLessFile: [/(\/|\\)components(\/|\\)style(\/|\\)default.less$/],
|
|
||||||
transformTSFile(file) {
|
|
||||||
if (isComponentStyleEntry(file)) {
|
|
||||||
let content = file.contents.toString();
|
|
||||||
|
|
||||||
if (needTransformStyle(content)) {
|
|
||||||
const cloneFile = file.clone();
|
|
||||||
|
|
||||||
// Origin
|
|
||||||
content = content.replace('../../style/index.less', '../../style/default.less');
|
|
||||||
cloneFile.contents = Buffer.from(content);
|
|
||||||
|
|
||||||
return cloneFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
transformFile(file) {
|
|
||||||
if (isComponentStyleEntry(file)) {
|
|
||||||
const indexLessFilePath = file.path.replace('index.tsx', 'index.less');
|
|
||||||
|
|
||||||
if (fs.existsSync(indexLessFilePath)) {
|
|
||||||
// We put origin `index.less` file to `index-pure.less`
|
|
||||||
const pureFile = file.clone();
|
|
||||||
pureFile.contents = Buffer.from(fs.readFileSync(indexLessFilePath, 'utf8'));
|
|
||||||
pureFile.path = pureFile.path.replace('index.tsx', 'index-pure.less');
|
|
||||||
|
|
||||||
// Rewrite `index.less` file with `root-entry-name`
|
|
||||||
const indexLessFile = file.clone();
|
|
||||||
indexLessFile.contents = Buffer.from(
|
|
||||||
[
|
|
||||||
// Inject variable
|
|
||||||
'@root-entry-name: default;',
|
|
||||||
// Point to origin file
|
|
||||||
"@import './index-pure.less';",
|
|
||||||
].join('\n\n'),
|
|
||||||
);
|
|
||||||
indexLessFile.path = indexLessFile.path.replace('index.tsx', 'index.less');
|
|
||||||
|
|
||||||
return [indexLessFile, pureFile];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
lessConfig: {
|
|
||||||
modifyVars: {
|
|
||||||
'root-entry-name': 'default',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
finalize: finalizeCompile,
|
finalize: finalizeCompile,
|
||||||
},
|
},
|
||||||
dist: {
|
dist: {
|
||||||
finalize: finalizeDist,
|
finalize: finalizeDist,
|
||||||
},
|
},
|
||||||
generateThemeFileContent,
|
|
||||||
bail: true,
|
bail: true,
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,6 +59,7 @@ jspm_packages/
|
||||||
dist
|
dist
|
||||||
lib
|
lib
|
||||||
es
|
es
|
||||||
|
/locale
|
||||||
_site
|
_site
|
||||||
yarn.lock
|
yarn.lock
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
@ -78,5 +79,8 @@ report.html
|
||||||
|
|
||||||
site/src/router/demoRoutes.js
|
site/src/router/demoRoutes.js
|
||||||
|
|
||||||
|
components/version/version.ts
|
||||||
components/version/version.tsx
|
components/version/version.tsx
|
||||||
|
components/version/token.json
|
||||||
|
components/version/token-meta.json
|
||||||
~component-api.json
|
~component-api.json
|
||||||
|
|
9
.jest.js
9
.jest.js
|
@ -18,6 +18,7 @@ function getTestRegex(libDir) {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
verbose: true,
|
verbose: true,
|
||||||
setupFiles: ['./tests/setup.js'],
|
setupFiles: ['./tests/setup.js'],
|
||||||
|
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||||
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'vue', 'md', 'jpg'],
|
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx', 'json', 'vue', 'md', 'jpg'],
|
||||||
modulePathIgnorePatterns: ['/_site/'],
|
modulePathIgnorePatterns: ['/_site/'],
|
||||||
testPathIgnorePatterns: testPathIgnorePatterns,
|
testPathIgnorePatterns: testPathIgnorePatterns,
|
||||||
|
@ -30,23 +31,19 @@ module.exports = {
|
||||||
testRegex: getTestRegex(libDir),
|
testRegex: getTestRegex(libDir),
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^@/(.*)$/': '<rootDir>/$1',
|
'^@/(.*)$/': '<rootDir>/$1',
|
||||||
'ant-design-vue$/': '<rootDir>/components/index.ts',
|
'^ant-design-vue$': '<rootDir>/components/index',
|
||||||
'ant-design-vue/es/': '<rootDir>/components',
|
'^ant-design-vue/es/(.*)$': '<rootDir>/components/$1',
|
||||||
},
|
},
|
||||||
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
||||||
collectCoverage: process.env.COVERAGE === 'true',
|
collectCoverage: process.env.COVERAGE === 'true',
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'components/**/*.{js,jsx,vue}',
|
'components/**/*.{js,jsx,vue}',
|
||||||
'!components/*/style/index.{js,jsx}',
|
|
||||||
'!components/style/*.{js,jsx}',
|
|
||||||
'!components/*/locale/*.{js,jsx}',
|
|
||||||
'!components/*/__tests__/**/type.{js,jsx}',
|
'!components/*/__tests__/**/type.{js,jsx}',
|
||||||
'!components/vc-*/**/*',
|
'!components/vc-*/**/*',
|
||||||
'!components/*/demo/**/*',
|
'!components/*/demo/**/*',
|
||||||
'!components/_util/**/*',
|
'!components/_util/**/*',
|
||||||
'!components/align/**/*',
|
'!components/align/**/*',
|
||||||
'!components/trigger/**/*',
|
'!components/trigger/**/*',
|
||||||
'!components/style.js',
|
|
||||||
'!**/node_modules/**',
|
'!**/node_modules/**',
|
||||||
],
|
],
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
|
|
|
@ -18,7 +18,6 @@ yarn-error.log
|
||||||
.editorconfig
|
.editorconfig
|
||||||
.eslintignore
|
.eslintignore
|
||||||
**/*.yml
|
**/*.yml
|
||||||
components/style/color/*.less
|
|
||||||
**/assets
|
**/assets
|
||||||
.gitattributes
|
.gitattributes
|
||||||
.stylelintrc
|
.stylelintrc
|
||||||
|
|
|
@ -4,13 +4,40 @@
|
||||||
"stylelint-config-rational-order",
|
"stylelint-config-rational-order",
|
||||||
"stylelint-config-prettier"
|
"stylelint-config-prettier"
|
||||||
],
|
],
|
||||||
"plugins": ["stylelint-order", "stylelint-declaration-block-no-ignored-properties"],
|
"customSyntax": "postcss-less",
|
||||||
|
"plugins": ["stylelint-declaration-block-no-ignored-properties"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"comment-empty-line-before": null,
|
"function-name-case": ["lower"],
|
||||||
"function-name-case": ["lower", { "ignoreFunctions": ["/colorPalette/"] }],
|
"function-no-unknown": [
|
||||||
"no-invalid-double-slash-comments": null,
|
true,
|
||||||
|
{
|
||||||
|
"ignoreFunctions": [
|
||||||
|
"fade",
|
||||||
|
"fadeout",
|
||||||
|
"tint",
|
||||||
|
"darken",
|
||||||
|
"ceil",
|
||||||
|
"fadein",
|
||||||
|
"floor",
|
||||||
|
"unit",
|
||||||
|
"shade",
|
||||||
|
"lighten",
|
||||||
|
"percentage",
|
||||||
|
"-"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import-notation": null,
|
||||||
"no-descending-specificity": null,
|
"no-descending-specificity": null,
|
||||||
"declaration-empty-line-before": null
|
"no-invalid-position-at-import-rule": null,
|
||||||
},
|
"declaration-empty-line-before": null,
|
||||||
"ignoreFiles": ["components/style/color/{bezierEasing,colorPalette,tinyColor}.less"]
|
"keyframes-name-pattern": null,
|
||||||
|
"custom-property-pattern": null,
|
||||||
|
"number-max-precision": 8,
|
||||||
|
"alpha-value-notation": "number",
|
||||||
|
"color-function-notation": "legacy",
|
||||||
|
"selector-class-pattern": null,
|
||||||
|
"selector-id-pattern": null,
|
||||||
|
"selector-not-notation": null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1357
CHANGELOG.en-US.md
1357
CHANGELOG.en-US.md
File diff suppressed because it is too large
Load Diff
1356
CHANGELOG.zh-CN.md
1356
CHANGELOG.zh-CN.md
File diff suppressed because it is too large
Load Diff
|
@ -66,6 +66,7 @@ $ yarn add ant-design-vue
|
||||||
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | 使用 vue-cli3 快速使用 ant-design-vue 组件库 |
|
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | 使用 vue-cli3 快速使用 ant-design-vue 组件库 |
|
||||||
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | 在 DOM 模板中,您可以使用 ant-design-vue 组件的自定义事件(camelCase) |
|
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | 在 DOM 模板中,您可以使用 ant-design-vue 组件的自定义事件(camelCase) |
|
||||||
| [@formily/antdv](https://github.com/formilyjs/antdv) | 这是一个结合了 Formily 和 ant-design-vue 的组件库 |
|
| [@formily/antdv](https://github.com/formilyjs/antdv) | 这是一个结合了 Formily 和 ant-design-vue 的组件库 |
|
||||||
|
| [@ant-design-vue/nuxt](https://github.com/vueComponent/ant-design-vue-nuxt) | ant-design-vue 的 nuxt 模块扩展 |
|
||||||
|
|
||||||
## 问答
|
## 问答
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ English | [简体中文](./README-zh_CN.md)
|
||||||
|
|
||||||
## Environment Support
|
## Environment Support
|
||||||
|
|
||||||
- Modern browsers. v1.x support Internet Explorer 9+ (with [polyfills](https://www.antdv.com/docs/vue/getting-started/#Compatibility))
|
- Modern browsers. v1.x support Internet Explorer 9+ (with [polyfills](https://www.antdv.com/docs/vue/getting-started/#compatibility))
|
||||||
- Server-side Rendering
|
- Server-side Rendering
|
||||||
- Support Vue 2 & Vue 3
|
- Support Vue 2 & Vue 3
|
||||||
- [Electron](https://electronjs.org/)
|
- [Electron](https://electronjs.org/)
|
||||||
|
@ -66,6 +66,7 @@ If you are in a bad network environment,you can try other registries and tools
|
||||||
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | Vue-cli 3 plugin to add ant-design-vue |
|
| [vue-cli-plugin-ant-design](https://github.com/vueComponent/vue-cli-plugin-ant-design) | Vue-cli 3 plugin to add ant-design-vue |
|
||||||
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | The library function, implemented in the DOM template, can use the custom event of the ant-design-vue component (camelCase) |
|
| [vue-dash-event](https://github.com/vueComponent/vue-dash-event) | The library function, implemented in the DOM template, can use the custom event of the ant-design-vue component (camelCase) |
|
||||||
| [@formily/antdv](https://github.com/formilyjs/antdv) | The Library with Formily and ant-design-vue |
|
| [@formily/antdv](https://github.com/formilyjs/antdv) | The Library with Formily and ant-design-vue |
|
||||||
|
| [@ant-design-vue/nuxt](https://github.com/vueComponent/ant-design-vue-nuxt) | A nuxt module for ant-design-vue |
|
||||||
|
|
||||||
## Donation
|
## Donation
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ export function formatter(
|
||||||
!tableTitle.includes('()')
|
!tableTitle.includes('()')
|
||||||
) {
|
) {
|
||||||
const childTag: VueTag = {
|
const childTag: VueTag = {
|
||||||
name: getComponentName(tableTitle.replaceAll('.', '').replaceAll('/', ''), tagPrefix),
|
name: getComponentName(tableTitle.replace(/\.|\//g, ''), tagPrefix),
|
||||||
slots: [],
|
slots: [],
|
||||||
events: [],
|
events: [],
|
||||||
attributes: [],
|
attributes: [],
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { outputFileSync, readFileSync } from 'fs-extra';
|
||||||
import type { Options, VueTag } from './type';
|
import type { Options, VueTag } from './type';
|
||||||
import { getComponentName, normalizePath, toKebabCase } from './utils';
|
import { getComponentName, normalizePath, toKebabCase } from './utils';
|
||||||
import { genVeturAttributes, genVeturTags } from './vetur';
|
import { genVeturAttributes, genVeturTags } from './vetur';
|
||||||
|
import { flatMap } from 'lodash';
|
||||||
|
|
||||||
async function readMarkdown(options: Options): Promise<Map<String, VueTag>> {
|
async function readMarkdown(options: Options): Promise<Map<String, VueTag>> {
|
||||||
const mdPaths = await glob(normalizePath(`${options.path}/**/*.md`));
|
const mdPaths = await glob(normalizePath(`${options.path}/**/*.md`));
|
||||||
|
@ -22,7 +23,7 @@ async function readMarkdown(options: Options): Promise<Map<String, VueTag>> {
|
||||||
})
|
})
|
||||||
.filter(item => item) as VueTag[][];
|
.filter(item => item) as VueTag[][];
|
||||||
const tags: Map<String, VueTag> = new Map();
|
const tags: Map<String, VueTag> = new Map();
|
||||||
data.flatMap(item => item).forEach(mergedTag => mergeTag(tags, mergedTag));
|
flatMap(data, item => item).forEach(mergedTag => mergeTag(tags, mergedTag));
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ function readLine(input: string) {
|
||||||
function splitTableLine(line: string) {
|
function splitTableLine(line: string) {
|
||||||
line = line.replace(/\\\|/g, 'JOIN');
|
line = line.replace(/\\\|/g, 'JOIN');
|
||||||
|
|
||||||
const items = line.split('|').map(item => item.trim().replaceAll('JOIN', '|'));
|
const items = line.split('|').map(item => item.trim().replace(/JOIN/g, '|'));
|
||||||
|
|
||||||
// remove pipe character on both sides
|
// remove pipe character on both sides
|
||||||
items.pop();
|
items.pop();
|
||||||
|
|
|
@ -20,7 +20,8 @@ module.exports = function (modules) {
|
||||||
resolve('@babel/plugin-transform-runtime'),
|
resolve('@babel/plugin-transform-runtime'),
|
||||||
{
|
{
|
||||||
useESModules: modules === false,
|
useESModules: modules === false,
|
||||||
version: '^7.10.4',
|
version:
|
||||||
|
require(`${process.cwd()}/package.json`).dependencies['@babel/runtime'] || '^7.10.4',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// resolve('babel-plugin-inline-import-data-uri'),
|
// resolve('babel-plugin-inline-import-data-uri'),
|
||||||
|
|
|
@ -150,36 +150,6 @@ function getWebpackConfig(modules) {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.less$/,
|
|
||||||
use: [
|
|
||||||
MiniCssExtractPlugin.loader,
|
|
||||||
{
|
|
||||||
loader: 'css-loader',
|
|
||||||
options: {
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'postcss-loader',
|
|
||||||
options: {
|
|
||||||
postcssOptions: {
|
|
||||||
plugins: ['autoprefixer'],
|
|
||||||
},
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'less-loader',
|
|
||||||
options: {
|
|
||||||
lessOptions: {
|
|
||||||
javascriptEnabled: true,
|
|
||||||
},
|
|
||||||
sourceMap: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Images
|
// Images
|
||||||
{
|
{
|
||||||
test: svgRegex,
|
test: svgRegex,
|
||||||
|
@ -200,7 +170,7 @@ function getWebpackConfig(modules) {
|
||||||
new webpack.BannerPlugin(`
|
new webpack.BannerPlugin(`
|
||||||
${pkg.name} v${pkg.version}
|
${pkg.name} v${pkg.version}
|
||||||
|
|
||||||
Copyright 2017-present, ant-design-vue.
|
Copyright 2017-present, Ant Design Vue.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
`),
|
`),
|
||||||
new WebpackBar({
|
new WebpackBar({
|
||||||
|
@ -215,7 +185,7 @@ All rights reserved.
|
||||||
};
|
};
|
||||||
|
|
||||||
if (process.env.RUN_ENV === 'PRODUCTION') {
|
if (process.env.RUN_ENV === 'PRODUCTION') {
|
||||||
const entry = ['./index'];
|
let entry = ['./index'];
|
||||||
config.externals = [
|
config.externals = [
|
||||||
{
|
{
|
||||||
vue: {
|
vue: {
|
||||||
|
@ -223,11 +193,13 @@ All rights reserved.
|
||||||
commonjs2: 'vue',
|
commonjs2: 'vue',
|
||||||
commonjs: 'vue',
|
commonjs: 'vue',
|
||||||
amd: 'vue',
|
amd: 'vue',
|
||||||
|
module: 'vue',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
config.output.library = distFileBaseName;
|
config.output.library = distFileBaseName;
|
||||||
config.output.libraryTarget = 'umd';
|
config.output.libraryTarget = 'umd';
|
||||||
|
config.output.globalObject = 'this';
|
||||||
config.optimization = {
|
config.optimization = {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new TerserPlugin({
|
new TerserPlugin({
|
||||||
|
@ -238,7 +210,6 @@ All rights reserved.
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Development
|
// Development
|
||||||
const uncompressedConfig = merge({}, config, {
|
const uncompressedConfig = merge({}, config, {
|
||||||
entry: {
|
entry: {
|
||||||
|
|
|
@ -5,7 +5,6 @@ const getBabelCommonConfig = require('./getBabelCommonConfig');
|
||||||
const merge2 = require('merge2');
|
const merge2 = require('merge2');
|
||||||
const { execSync } = require('child_process');
|
const { execSync } = require('child_process');
|
||||||
const through2 = require('through2');
|
const through2 = require('through2');
|
||||||
const transformLess = require('./transformLess');
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const babel = require('gulp-babel');
|
const babel = require('gulp-babel');
|
||||||
const argv = require('minimist')(process.argv.slice(2));
|
const argv = require('minimist')(process.argv.slice(2));
|
||||||
|
@ -27,15 +26,22 @@ const compareVersions = require('compare-versions');
|
||||||
const getTSCommonConfig = require('./getTSCommonConfig');
|
const getTSCommonConfig = require('./getTSCommonConfig');
|
||||||
const replaceLib = require('./replaceLib');
|
const replaceLib = require('./replaceLib');
|
||||||
const sortApiTable = require('./sortApiTable');
|
const sortApiTable = require('./sortApiTable');
|
||||||
|
const { glob } = require('glob');
|
||||||
|
|
||||||
const packageJson = require(getProjectPath('package.json'));
|
const packageJson = require(getProjectPath('package.json'));
|
||||||
const tsDefaultReporter = ts.reporter.defaultReporter();
|
const tsDefaultReporter = ts.reporter.defaultReporter();
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
const libDir = getProjectPath('lib');
|
const libDir = getProjectPath('lib');
|
||||||
const esDir = getProjectPath('es');
|
const esDir = getProjectPath('es');
|
||||||
|
const localeDir = getProjectPath('locale');
|
||||||
|
|
||||||
const tsConfig = getTSCommonConfig();
|
const tsConfig = getTSCommonConfig();
|
||||||
|
|
||||||
|
// FIXME: hard code, not find typescript can modify the path resolution
|
||||||
|
const localeDts = `import type { Locale } from '../lib/locale-provider';
|
||||||
|
declare const localeValues: Locale;
|
||||||
|
export default localeValues;`;
|
||||||
|
|
||||||
function dist(done) {
|
function dist(done) {
|
||||||
rimraf.sync(path.join(cwd, 'dist'));
|
rimraf.sync(path.join(cwd, 'dist'));
|
||||||
process.env.RUN_ENV = 'PRODUCTION';
|
process.env.RUN_ENV = 'PRODUCTION';
|
||||||
|
@ -108,6 +114,11 @@ gulp.task('tsc', () =>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gulp.task('clean', () => {
|
||||||
|
rimraf.sync(getProjectPath('_site'));
|
||||||
|
rimraf.sync(getProjectPath('_data'));
|
||||||
|
});
|
||||||
|
|
||||||
function babelify(js, modules) {
|
function babelify(js, modules) {
|
||||||
const babelConfig = getBabelCommonConfig(modules);
|
const babelConfig = getBabelCommonConfig(modules);
|
||||||
babelConfig.babelrc = false;
|
babelConfig.babelrc = false;
|
||||||
|
@ -118,17 +129,7 @@ function babelify(js, modules) {
|
||||||
const stream = js.pipe(babel(babelConfig)).pipe(
|
const stream = js.pipe(babel(babelConfig)).pipe(
|
||||||
through2.obj(function z(file, encoding, next) {
|
through2.obj(function z(file, encoding, next) {
|
||||||
this.push(file.clone());
|
this.push(file.clone());
|
||||||
if (file.path.match(/\/style\/index\.(js|jsx|ts|tsx)$/)) {
|
if (modules !== false) {
|
||||||
const content = file.contents.toString(encoding);
|
|
||||||
file.contents = Buffer.from(
|
|
||||||
content
|
|
||||||
.replace(/\/style\/?'/g, "/style/css'")
|
|
||||||
.replace(/\/style\/?"/g, '/style/css"')
|
|
||||||
.replace(/\.less/g, '.css'),
|
|
||||||
);
|
|
||||||
file.path = file.path.replace(/index\.(js|jsx|ts|tsx)$/, 'css.js');
|
|
||||||
this.push(file);
|
|
||||||
} else if (modules !== false) {
|
|
||||||
const content = file.contents.toString(encoding);
|
const content = file.contents.toString(encoding);
|
||||||
file.contents = Buffer.from(
|
file.contents = Buffer.from(
|
||||||
content
|
content
|
||||||
|
@ -144,47 +145,9 @@ function babelify(js, modules) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function compile(modules) {
|
function compile(modules) {
|
||||||
const { compile: { transformTSFile, transformFile, includeLessFile = [] } = {} } = getConfig();
|
const { compile: { transformTSFile, transformFile } = {} } = getConfig();
|
||||||
rimraf.sync(modules !== false ? libDir : esDir);
|
rimraf.sync(modules !== false ? libDir : esDir);
|
||||||
|
|
||||||
// =============================== LESS ===============================
|
|
||||||
const less = gulp
|
|
||||||
.src(['components/**/*.less'])
|
|
||||||
.pipe(
|
|
||||||
through2.obj(function (file, encoding, next) {
|
|
||||||
// Replace content
|
|
||||||
const cloneFile = file.clone();
|
|
||||||
const content = file.contents.toString().replace(/^\uFEFF/, '');
|
|
||||||
|
|
||||||
cloneFile.contents = Buffer.from(content);
|
|
||||||
|
|
||||||
// Clone for css here since `this.push` will modify file.path
|
|
||||||
const cloneCssFile = cloneFile.clone();
|
|
||||||
|
|
||||||
this.push(cloneFile);
|
|
||||||
|
|
||||||
// Transform less file
|
|
||||||
if (
|
|
||||||
file.path.match(/(\/|\\)style(\/|\\)index\.less$/) ||
|
|
||||||
file.path.match(/(\/|\\)style(\/|\\)v2-compatible-reset\.less$/) ||
|
|
||||||
includeLessFile.some(regex => file.path.match(regex))
|
|
||||||
) {
|
|
||||||
transformLess(cloneCssFile.contents.toString(), cloneCssFile.path)
|
|
||||||
.then(css => {
|
|
||||||
cloneCssFile.contents = Buffer.from(css);
|
|
||||||
cloneCssFile.path = cloneCssFile.path.replace(/\.less$/, '.css');
|
|
||||||
this.push(cloneCssFile);
|
|
||||||
next();
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
console.error(e);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
|
||||||
const assets = gulp
|
const assets = gulp
|
||||||
.src(['components/**/*.@(png|svg)'])
|
.src(['components/**/*.@(png|svg)'])
|
||||||
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||||
|
@ -259,7 +222,26 @@ function compile(modules) {
|
||||||
tsResult.on('end', check);
|
tsResult.on('end', check);
|
||||||
const tsFilesStream = babelify(tsResult.js, modules);
|
const tsFilesStream = babelify(tsResult.js, modules);
|
||||||
const tsd = tsResult.dts.pipe(gulp.dest(modules === false ? esDir : libDir));
|
const tsd = tsResult.dts.pipe(gulp.dest(modules === false ? esDir : libDir));
|
||||||
return merge2([less, tsFilesStream, tsd, assets, transformFileStream].filter(s => s));
|
return merge2([tsFilesStream, tsd, assets, transformFileStream].filter(s => s));
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateLocale() {
|
||||||
|
if (!fs.existsSync(localeDir)) {
|
||||||
|
fs.mkdirSync(localeDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const localeFiles = glob.sync('components/locale/*.ts?(x)');
|
||||||
|
localeFiles.forEach(item => {
|
||||||
|
const match = item.match(/components\/locale\/(.*)\.tsx?/);
|
||||||
|
if (match) {
|
||||||
|
const locale = match[1];
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(localeDir, `${locale}.js`),
|
||||||
|
`module.exports = require('../lib/locale/${locale}');`,
|
||||||
|
);
|
||||||
|
fs.writeFileSync(path.join(localeDir, `${locale}.d.ts`), localeDts);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function tag() {
|
function tag() {
|
||||||
|
@ -395,7 +377,10 @@ gulp.task('compile-with-es', done => {
|
||||||
|
|
||||||
gulp.task('compile-with-lib', done => {
|
gulp.task('compile-with-lib', done => {
|
||||||
console.log('[Parallel] Compile to js...');
|
console.log('[Parallel] Compile to js...');
|
||||||
compile().on('finish', done);
|
compile().on('finish', () => {
|
||||||
|
generateLocale();
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('compile-finalize', done => {
|
gulp.task('compile-finalize', done => {
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
const less = require('less');
|
|
||||||
const path = require('path');
|
|
||||||
const postcss = require('postcss');
|
|
||||||
const autoprefixer = require('autoprefixer');
|
|
||||||
const NpmImportPlugin = require('less-plugin-npm-import');
|
|
||||||
const { getConfig } = require('./utils/projectHelper');
|
|
||||||
|
|
||||||
function transformLess(lessContent, lessFilePath, config = {}) {
|
|
||||||
const { cwd = process.cwd() } = config;
|
|
||||||
const { compile: { lessConfig } = {} } = getConfig();
|
|
||||||
const resolvedLessFile = path.resolve(cwd, lessFilePath);
|
|
||||||
|
|
||||||
// Do less compile
|
|
||||||
const lessOpts = {
|
|
||||||
paths: [path.dirname(resolvedLessFile)],
|
|
||||||
filename: resolvedLessFile,
|
|
||||||
plugins: [new NpmImportPlugin({ prefix: '~' })],
|
|
||||||
javascriptEnabled: true,
|
|
||||||
...lessConfig,
|
|
||||||
};
|
|
||||||
return less
|
|
||||||
.render(lessContent, lessOpts)
|
|
||||||
.then(result => postcss([autoprefixer]).process(result.css, { from: undefined }))
|
|
||||||
.then(r => r.css);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = transformLess;
|
|
|
@ -1,11 +0,0 @@
|
||||||
// We convert less import in es/lib to css file path
|
|
||||||
function cssInjection(content) {
|
|
||||||
return content
|
|
||||||
.replace(/\/style\/?'/g, "/style/css'")
|
|
||||||
.replace(/\/style\/?"/g, '/style/css"')
|
|
||||||
.replace(/\.less/g, '.css');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
cssInjection,
|
|
||||||
};
|
|
|
@ -1,10 +1,12 @@
|
||||||
import type { ExtractPropTypes, PropType } from 'vue';
|
import type { ExtractPropTypes, PropType } from 'vue';
|
||||||
import { onMounted, ref, defineComponent, onBeforeUnmount } from 'vue';
|
import { shallowRef, onMounted, defineComponent, onBeforeUnmount } from 'vue';
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
import type { ButtonProps } from '../button';
|
import type { ButtonProps } from '../button';
|
||||||
import type { LegacyButtonType } from '../button/buttonTypes';
|
import type { LegacyButtonType } from '../button/buttonTypes';
|
||||||
import { convertLegacyProps } from '../button/buttonTypes';
|
import { convertLegacyProps } from '../button/buttonTypes';
|
||||||
import useDestroyed from './hooks/useDestroyed';
|
import useDestroyed from './hooks/useDestroyed';
|
||||||
|
import { objectType } from './type';
|
||||||
|
import { findDOMNode } from './props-util';
|
||||||
|
|
||||||
const actionButtonProps = {
|
const actionButtonProps = {
|
||||||
type: {
|
type: {
|
||||||
|
@ -14,15 +16,15 @@ const actionButtonProps = {
|
||||||
close: Function,
|
close: Function,
|
||||||
autofocus: Boolean,
|
autofocus: Boolean,
|
||||||
prefixCls: String,
|
prefixCls: String,
|
||||||
buttonProps: Object as PropType<ButtonProps>,
|
buttonProps: objectType<ButtonProps>(),
|
||||||
emitEvent: Boolean,
|
emitEvent: Boolean,
|
||||||
quitOnNullishReturnValue: Boolean,
|
quitOnNullishReturnValue: Boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ActionButtonProps = ExtractPropTypes<typeof actionButtonProps>;
|
export type ActionButtonProps = ExtractPropTypes<typeof actionButtonProps>;
|
||||||
|
|
||||||
function isThenable(thing?: PromiseLike<any>): boolean {
|
function isThenable<T>(thing?: PromiseLike<T>): boolean {
|
||||||
return !!(thing && !!thing.then);
|
return !!(thing && thing.then);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -30,22 +32,25 @@ export default defineComponent({
|
||||||
name: 'ActionButton',
|
name: 'ActionButton',
|
||||||
props: actionButtonProps,
|
props: actionButtonProps,
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const clickedRef = ref<boolean>(false);
|
const clickedRef = shallowRef<boolean>(false);
|
||||||
const buttonRef = ref();
|
const buttonRef = shallowRef();
|
||||||
const loading = ref(false);
|
const loading = shallowRef(false);
|
||||||
let timeoutId: any;
|
let timeoutId: any;
|
||||||
const isDestroyed = useDestroyed();
|
const isDestroyed = useDestroyed();
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.autofocus) {
|
if (props.autofocus) {
|
||||||
timeoutId = setTimeout(() => buttonRef.value.$el?.focus());
|
timeoutId = setTimeout(() => findDOMNode(buttonRef.value)?.focus?.());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onInternalClose = (...args: any[]) => {
|
||||||
|
props.close?.(...args);
|
||||||
|
};
|
||||||
|
|
||||||
const handlePromiseOnOk = (returnValueOfOnOk?: PromiseLike<any>) => {
|
const handlePromiseOnOk = (returnValueOfOnOk?: PromiseLike<any>) => {
|
||||||
const { close } = props;
|
|
||||||
if (!isThenable(returnValueOfOnOk)) {
|
if (!isThenable(returnValueOfOnOk)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -55,48 +60,46 @@ export default defineComponent({
|
||||||
if (!isDestroyed.value) {
|
if (!isDestroyed.value) {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
close(...args);
|
onInternalClose(...args);
|
||||||
clickedRef.value = false;
|
clickedRef.value = false;
|
||||||
},
|
},
|
||||||
(e: Error) => {
|
(e: Error) => {
|
||||||
// Emit error when catch promise reject
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(e);
|
|
||||||
// See: https://github.com/ant-design/ant-design/issues/6183
|
// See: https://github.com/ant-design/ant-design/issues/6183
|
||||||
if (!isDestroyed.value) {
|
if (!isDestroyed.value) {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
clickedRef.value = false;
|
clickedRef.value = false;
|
||||||
|
return Promise.reject(e);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClick = (e: MouseEvent) => {
|
const onClick = (e: MouseEvent) => {
|
||||||
const { actionFn, close = () => {} } = props;
|
const { actionFn } = props;
|
||||||
if (clickedRef.value) {
|
if (clickedRef.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clickedRef.value = true;
|
clickedRef.value = true;
|
||||||
if (!actionFn) {
|
if (!actionFn) {
|
||||||
close();
|
onInternalClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let returnValueOfOnOk;
|
let returnValueOfOnOk: PromiseLike<any>;
|
||||||
if (props.emitEvent) {
|
if (props.emitEvent) {
|
||||||
returnValueOfOnOk = actionFn(e);
|
returnValueOfOnOk = actionFn(e);
|
||||||
if (props.quitOnNullishReturnValue && !isThenable(returnValueOfOnOk)) {
|
if (props.quitOnNullishReturnValue && !isThenable(returnValueOfOnOk)) {
|
||||||
clickedRef.value = false;
|
clickedRef.value = false;
|
||||||
close(e);
|
onInternalClose(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (actionFn.length) {
|
} else if (actionFn.length) {
|
||||||
returnValueOfOnOk = actionFn(close);
|
returnValueOfOnOk = actionFn(props.close);
|
||||||
// https://github.com/ant-design/ant-design/issues/23358
|
// https://github.com/ant-design/ant-design/issues/23358
|
||||||
clickedRef.value = false;
|
clickedRef.value = false;
|
||||||
} else {
|
} else {
|
||||||
returnValueOfOnOk = actionFn();
|
returnValueOfOnOk = actionFn();
|
||||||
if (!returnValueOfOnOk) {
|
if (!returnValueOfOnOk) {
|
||||||
close();
|
onInternalClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { defineComponent, ref, withDirectives } from 'vue';
|
import { defineComponent, shallowRef, withDirectives } from 'vue';
|
||||||
import antInput from './antInputDirective';
|
import antInput from './antInputDirective';
|
||||||
import PropTypes from './vue-types';
|
import PropTypes from './vue-types';
|
||||||
const BaseInput = defineComponent({
|
const BaseInput = defineComponent({
|
||||||
|
@ -8,7 +8,7 @@ const BaseInput = defineComponent({
|
||||||
},
|
},
|
||||||
emits: ['change', 'input'],
|
emits: ['change', 'input'],
|
||||||
setup(_p, { emit }) {
|
setup(_p, { emit }) {
|
||||||
const inputRef = ref(null);
|
const inputRef = shallowRef(null);
|
||||||
const handleChange = (e: Event) => {
|
const handleChange = (e: Event) => {
|
||||||
const { composing } = e.target as any;
|
const { composing } = e.target as any;
|
||||||
if ((e as any).isComposing || composing) {
|
if ((e as any).isComposing || composing) {
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import PropTypes from './vue-types';
|
import PropTypes from './vue-types';
|
||||||
import switchScrollingEffect from './switchScrollingEffect';
|
|
||||||
import setStyle from './setStyle';
|
|
||||||
import Portal from './Portal';
|
import Portal from './Portal';
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
ref,
|
shallowRef,
|
||||||
watch,
|
watch,
|
||||||
onMounted,
|
onMounted,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
onUpdated,
|
onUpdated,
|
||||||
getCurrentInstance,
|
getCurrentInstance,
|
||||||
nextTick,
|
nextTick,
|
||||||
|
computed,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import canUseDom from './canUseDom';
|
import canUseDom from './canUseDom';
|
||||||
import ScrollLocker from '../vc-util/Dom/scrollLocker';
|
|
||||||
import raf from './raf';
|
import raf from './raf';
|
||||||
|
import { booleanType } from './type';
|
||||||
|
import useScrollLocker from './hooks/useScrollLocker';
|
||||||
|
|
||||||
let openCount = 0;
|
let openCount = 0;
|
||||||
const supportDom = canUseDom();
|
const supportDom = canUseDom();
|
||||||
|
@ -24,17 +24,13 @@ export function getOpenCount() {
|
||||||
return process.env.NODE_ENV === 'test' ? openCount : 0;
|
return process.env.NODE_ENV === 'test' ? openCount : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/19340
|
|
||||||
// https://github.com/ant-design/ant-design/issues/19332
|
|
||||||
let cacheOverflow = {};
|
|
||||||
|
|
||||||
const getParent = (getContainer: GetContainer) => {
|
const getParent = (getContainer: GetContainer) => {
|
||||||
if (!supportDom) {
|
if (!supportDom) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (getContainer) {
|
if (getContainer) {
|
||||||
if (typeof getContainer === 'string') {
|
if (typeof getContainer === 'string') {
|
||||||
return document.querySelectorAll(getContainer)[0];
|
return document.querySelectorAll(getContainer)[0] as HTMLElement;
|
||||||
}
|
}
|
||||||
if (typeof getContainer === 'function') {
|
if (typeof getContainer === 'function') {
|
||||||
return getContainer();
|
return getContainer();
|
||||||
|
@ -57,24 +53,25 @@ export default defineComponent({
|
||||||
forceRender: { type: Boolean, default: undefined },
|
forceRender: { type: Boolean, default: undefined },
|
||||||
getContainer: PropTypes.any,
|
getContainer: PropTypes.any,
|
||||||
visible: { type: Boolean, default: undefined },
|
visible: { type: Boolean, default: undefined },
|
||||||
|
autoLock: booleanType(),
|
||||||
|
didUpdate: Function,
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const container = ref<HTMLElement>();
|
const container = shallowRef<HTMLElement>();
|
||||||
const componentRef = ref();
|
const componentRef = shallowRef();
|
||||||
const rafId = ref<number>();
|
const rafId = shallowRef<number>();
|
||||||
const scrollLocker = new ScrollLocker({
|
|
||||||
container: getParent(props.getContainer) as HTMLElement,
|
|
||||||
});
|
|
||||||
|
|
||||||
const removeCurrentContainer = () => {
|
const removeCurrentContainer = () => {
|
||||||
// Portal will remove from `parentNode`.
|
// Portal will remove from `parentNode`.
|
||||||
// Let's handle this again to avoid refactor issue.
|
// Let's handle this again to avoid refactor issue.
|
||||||
container.value?.parentNode?.removeChild(container.value);
|
container.value?.parentNode?.removeChild(container.value);
|
||||||
|
container.value = null;
|
||||||
};
|
};
|
||||||
|
let parent: HTMLElement = null;
|
||||||
const attachToParent = (force = false) => {
|
const attachToParent = (force = false) => {
|
||||||
if (force || (container.value && !container.value.parentNode)) {
|
if (force || (container.value && !container.value.parentNode)) {
|
||||||
const parent = getParent(props.getContainer);
|
parent = getParent(props.getContainer);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent.appendChild(container.value);
|
parent.appendChild(container.value);
|
||||||
return true;
|
return true;
|
||||||
|
@ -86,13 +83,13 @@ export default defineComponent({
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
// attachToParent();
|
// attachToParent();
|
||||||
|
const defaultContainer = document.createElement('div');
|
||||||
const getContainer = () => {
|
const getContainer = () => {
|
||||||
if (!supportDom) {
|
if (!supportDom) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!container.value) {
|
if (!container.value) {
|
||||||
container.value = document.createElement('div');
|
container.value = defaultContainer;
|
||||||
attachToParent(true);
|
attachToParent(true);
|
||||||
}
|
}
|
||||||
setWrapperClassName();
|
setWrapperClassName();
|
||||||
|
@ -108,41 +105,33 @@ export default defineComponent({
|
||||||
setWrapperClassName();
|
setWrapperClassName();
|
||||||
attachToParent();
|
attachToParent();
|
||||||
});
|
});
|
||||||
/**
|
|
||||||
* Enhance ./switchScrollingEffect
|
|
||||||
* 1. Simulate document body scroll bar with
|
|
||||||
* 2. Record body has overflow style and recover when all of PortalWrapper invisible
|
|
||||||
* 3. Disable body scroll when PortalWrapper has open
|
|
||||||
*
|
|
||||||
* @memberof PortalWrapper
|
|
||||||
*/
|
|
||||||
const switchScrolling = () => {
|
|
||||||
if (openCount === 1 && !Object.keys(cacheOverflow).length) {
|
|
||||||
switchScrollingEffect();
|
|
||||||
// Must be set after switchScrollingEffect
|
|
||||||
cacheOverflow = setStyle({
|
|
||||||
overflow: 'hidden',
|
|
||||||
overflowX: 'hidden',
|
|
||||||
overflowY: 'hidden',
|
|
||||||
});
|
|
||||||
} else if (!openCount) {
|
|
||||||
setStyle(cacheOverflow);
|
|
||||||
cacheOverflow = {};
|
|
||||||
switchScrollingEffect(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
|
|
||||||
|
useScrollLocker(
|
||||||
|
computed(() => {
|
||||||
|
return (
|
||||||
|
props.autoLock &&
|
||||||
|
props.visible &&
|
||||||
|
canUseDom() &&
|
||||||
|
(container.value === document.body || container.value === defaultContainer)
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let init = false;
|
let init = false;
|
||||||
watch(
|
watch(
|
||||||
[() => props.visible, () => props.getContainer],
|
[() => props.visible, () => props.getContainer],
|
||||||
([visible, getContainer], [prevVisible, prevGetContainer]) => {
|
([visible, getContainer], [prevVisible, prevGetContainer]) => {
|
||||||
// Update count
|
// Update count
|
||||||
if (supportDom && getParent(props.getContainer) === document.body) {
|
if (supportDom) {
|
||||||
if (visible && !prevVisible) {
|
parent = getParent(props.getContainer);
|
||||||
openCount += 1;
|
if (parent === document.body) {
|
||||||
} else if (init) {
|
if (visible && !prevVisible) {
|
||||||
openCount -= 1;
|
openCount += 1;
|
||||||
|
} else if (init) {
|
||||||
|
openCount -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,17 +146,6 @@ export default defineComponent({
|
||||||
) {
|
) {
|
||||||
removeCurrentContainer();
|
removeCurrentContainer();
|
||||||
}
|
}
|
||||||
// updateScrollLocker
|
|
||||||
if (
|
|
||||||
visible &&
|
|
||||||
visible !== prevVisible &&
|
|
||||||
supportDom &&
|
|
||||||
getParent(getContainer) !== scrollLocker.getContainer()
|
|
||||||
) {
|
|
||||||
scrollLocker.reLock({
|
|
||||||
container: getParent(getContainer) as HTMLElement,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
init = true;
|
init = true;
|
||||||
},
|
},
|
||||||
|
@ -184,30 +162,27 @@ export default defineComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
const { visible, getContainer } = props;
|
const { visible } = props;
|
||||||
if (supportDom && getParent(getContainer) === document.body) {
|
if (supportDom && parent === document.body) {
|
||||||
// 离开时不会 render, 导到离开时数值不变,改用 func 。。
|
// 离开时不会 render, 导到离开时数值不变,改用 func 。。
|
||||||
openCount = visible && openCount ? openCount - 1 : openCount;
|
openCount = visible && openCount ? openCount - 1 : openCount;
|
||||||
}
|
}
|
||||||
removeCurrentContainer();
|
removeCurrentContainer();
|
||||||
raf.cancel(rafId.value);
|
raf.cancel(rafId.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { forceRender, visible } = props;
|
const { forceRender, visible } = props;
|
||||||
let portal = null;
|
let portal = null;
|
||||||
const childProps = {
|
const childProps = {
|
||||||
getOpenCount: () => openCount,
|
getOpenCount: () => openCount,
|
||||||
getContainer,
|
getContainer,
|
||||||
switchScrollingEffect: switchScrolling,
|
|
||||||
scrollLocker,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (forceRender || visible || componentRef.value) {
|
if (forceRender || visible || componentRef.value) {
|
||||||
portal = (
|
portal = (
|
||||||
<Portal
|
<Portal
|
||||||
getContainer={getContainer}
|
getContainer={getContainer}
|
||||||
ref={componentRef}
|
ref={componentRef}
|
||||||
|
didUpdate={props.didUpdate}
|
||||||
v-slots={{ default: () => slots.default?.(childProps) }}
|
v-slots={{ default: () => slots.default?.(childProps) }}
|
||||||
></Portal>
|
></Portal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,23 +1,34 @@
|
||||||
import type { ElementOf } from './type';
|
import type { PresetColorKey } from '../theme/interface';
|
||||||
import { tuple } from './type';
|
import { PresetColors } from '../theme/interface';
|
||||||
|
|
||||||
export const PresetStatusColorTypes = tuple('success', 'processing', 'error', 'default', 'warning');
|
type InverseColor = `${PresetColorKey}-inverse`;
|
||||||
|
const inverseColors = PresetColors.map<InverseColor>(color => `${color}-inverse`);
|
||||||
|
|
||||||
export const PresetColorTypes = tuple(
|
export const PresetStatusColorTypes = [
|
||||||
'pink',
|
'success',
|
||||||
'red',
|
'processing',
|
||||||
'yellow',
|
'error',
|
||||||
'orange',
|
'default',
|
||||||
'cyan',
|
'warning',
|
||||||
'green',
|
] as const;
|
||||||
'blue',
|
|
||||||
'purple',
|
|
||||||
'geekblue',
|
|
||||||
'magenta',
|
|
||||||
'volcano',
|
|
||||||
'gold',
|
|
||||||
'lime',
|
|
||||||
);
|
|
||||||
|
|
||||||
export type PresetColorType = ElementOf<typeof PresetColorTypes>;
|
export type PresetColorType = PresetColorKey | InverseColor;
|
||||||
export type PresetStatusColorType = ElementOf<typeof PresetStatusColorTypes>;
|
|
||||||
|
export type PresetStatusColorType = (typeof PresetStatusColorTypes)[number];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine if the color keyword belongs to the `Ant Design` {@link PresetColors}.
|
||||||
|
* @param color color to be judged
|
||||||
|
* @param includeInverse whether to include reversed colors
|
||||||
|
*/
|
||||||
|
export function isPresetColor(color?: any, includeInverse = true) {
|
||||||
|
if (includeInverse) {
|
||||||
|
return [...inverseColors, ...PresetColors].includes(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PresetColors.includes(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPresetStatusColor(color?: any): color is PresetStatusColorType {
|
||||||
|
return PresetStatusColorTypes.includes(color);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { inject, provide, reactive, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
function createContext<T extends Record<string, any>>(defaultValue?: T) {
|
||||||
|
const contextKey = Symbol('contextKey');
|
||||||
|
const useProvide = (props: T, newProps?: T) => {
|
||||||
|
const mergedProps = reactive<T>({} as T);
|
||||||
|
provide(contextKey, mergedProps);
|
||||||
|
watchEffect(() => {
|
||||||
|
Object.assign(mergedProps, props, newProps || {});
|
||||||
|
});
|
||||||
|
return mergedProps;
|
||||||
|
};
|
||||||
|
const useInject = () => {
|
||||||
|
return inject(contextKey, defaultValue as T) || ({} as T);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
useProvide,
|
||||||
|
useInject,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createContext;
|
|
@ -0,0 +1,25 @@
|
||||||
|
export type KeyType = string | number;
|
||||||
|
type ValueType = [number, any]; // [times, realValue]
|
||||||
|
|
||||||
|
class Entity {
|
||||||
|
/** @private Internal cache map. Do not access this directly */
|
||||||
|
cache = new Map<string, ValueType>();
|
||||||
|
|
||||||
|
get(keys: KeyType[] | string): ValueType | null {
|
||||||
|
return this.cache.get(Array.isArray(keys) ? keys.join('%') : keys) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(keys: KeyType[] | string, valueFn: (origin: ValueType | null) => ValueType | null) {
|
||||||
|
const path = Array.isArray(keys) ? keys.join('%') : keys;
|
||||||
|
const prevValue = this.cache.get(path)!;
|
||||||
|
const nextValue = valueFn(prevValue);
|
||||||
|
|
||||||
|
if (nextValue === null) {
|
||||||
|
this.cache.delete(path);
|
||||||
|
} else {
|
||||||
|
this.cache.set(path, nextValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Entity;
|
|
@ -0,0 +1,19 @@
|
||||||
|
import type { CSSInterpolation } from './hooks/useStyleRegister';
|
||||||
|
|
||||||
|
class Keyframe {
|
||||||
|
private name: string;
|
||||||
|
style: CSSInterpolation;
|
||||||
|
|
||||||
|
constructor(name: string, style: CSSInterpolation) {
|
||||||
|
this.name = name;
|
||||||
|
this.style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(hashId = ''): string {
|
||||||
|
return hashId ? `${hashId}-${this.name}` : this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyframe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Keyframe;
|
|
@ -0,0 +1,157 @@
|
||||||
|
import type { ShallowRef, ExtractPropTypes, InjectionKey, Ref } from 'vue';
|
||||||
|
import { provide, defineComponent, unref, inject, watch, shallowRef } from 'vue';
|
||||||
|
import CacheEntity from './Cache';
|
||||||
|
import type { Linter } from './linters/interface';
|
||||||
|
import type { Transformer } from './transformers/interface';
|
||||||
|
import { arrayType, booleanType, objectType, someType, stringType, withInstall } from '../type';
|
||||||
|
import initDefaultProps from '../props-util/initDefaultProps';
|
||||||
|
export const ATTR_TOKEN = 'data-token-hash';
|
||||||
|
export const ATTR_MARK = 'data-css-hash';
|
||||||
|
export const ATTR_DEV_CACHE_PATH = 'data-dev-cache-path';
|
||||||
|
|
||||||
|
// Mark css-in-js instance in style element
|
||||||
|
export const CSS_IN_JS_INSTANCE = '__cssinjs_instance__';
|
||||||
|
export const CSS_IN_JS_INSTANCE_ID = Math.random().toString(12).slice(2);
|
||||||
|
|
||||||
|
export function createCache() {
|
||||||
|
if (typeof document !== 'undefined' && document.head && document.body) {
|
||||||
|
const styles = document.body.querySelectorAll(`style[${ATTR_MARK}]`) || [];
|
||||||
|
const { firstChild } = document.head;
|
||||||
|
|
||||||
|
Array.from(styles).forEach(style => {
|
||||||
|
(style as any)[CSS_IN_JS_INSTANCE] =
|
||||||
|
(style as any)[CSS_IN_JS_INSTANCE] || CSS_IN_JS_INSTANCE_ID;
|
||||||
|
|
||||||
|
// Not force move if no head
|
||||||
|
document.head.insertBefore(style, firstChild);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Deduplicate of moved styles
|
||||||
|
const styleHash: Record<string, boolean> = {};
|
||||||
|
Array.from(document.querySelectorAll(`style[${ATTR_MARK}]`)).forEach(style => {
|
||||||
|
const hash = style.getAttribute(ATTR_MARK)!;
|
||||||
|
if (styleHash[hash]) {
|
||||||
|
if ((style as any)[CSS_IN_JS_INSTANCE] === CSS_IN_JS_INSTANCE_ID) {
|
||||||
|
style.parentNode?.removeChild(style);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
styleHash[hash] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CacheEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HashPriority = 'low' | 'high';
|
||||||
|
|
||||||
|
export interface StyleContextProps {
|
||||||
|
autoClear?: boolean;
|
||||||
|
/** @private Test only. Not work in production. */
|
||||||
|
mock?: 'server' | 'client';
|
||||||
|
/**
|
||||||
|
* Only set when you need ssr to extract style on you own.
|
||||||
|
* If not provided, it will auto create <style /> on the end of Provider in server side.
|
||||||
|
*/
|
||||||
|
cache: CacheEntity;
|
||||||
|
/** Tell children that this context is default generated context */
|
||||||
|
defaultCache: boolean;
|
||||||
|
/** Use `:where` selector to reduce hashId css selector priority */
|
||||||
|
hashPriority?: HashPriority;
|
||||||
|
/** Tell cssinjs where to inject style in */
|
||||||
|
container?: Element | ShadowRoot;
|
||||||
|
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
|
||||||
|
ssrInline?: boolean;
|
||||||
|
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
|
||||||
|
transformers?: Transformer[];
|
||||||
|
/**
|
||||||
|
* Linters to lint css before inject in document.
|
||||||
|
* Styles will be linted after transforming.
|
||||||
|
* Please note that `linters` do not support dynamic update.
|
||||||
|
*/
|
||||||
|
linters?: Linter[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyleContextKey: InjectionKey<ShallowRef<Partial<StyleContextProps>>> =
|
||||||
|
Symbol('StyleContextKey');
|
||||||
|
|
||||||
|
export type UseStyleProviderProps = Partial<StyleContextProps> | Ref<Partial<StyleContextProps>>;
|
||||||
|
const defaultStyleContext: StyleContextProps = {
|
||||||
|
cache: createCache(),
|
||||||
|
defaultCache: true,
|
||||||
|
hashPriority: 'low',
|
||||||
|
};
|
||||||
|
export const useStyleInject = () => {
|
||||||
|
return inject(StyleContextKey, shallowRef({ ...defaultStyleContext }));
|
||||||
|
};
|
||||||
|
export const useStyleProvider = (props: UseStyleProviderProps) => {
|
||||||
|
const parentContext = useStyleInject();
|
||||||
|
const context = shallowRef<Partial<StyleContextProps>>({ ...defaultStyleContext });
|
||||||
|
watch(
|
||||||
|
[props, parentContext],
|
||||||
|
() => {
|
||||||
|
const mergedContext: Partial<StyleContextProps> = {
|
||||||
|
...parentContext.value,
|
||||||
|
};
|
||||||
|
const propsValue = unref(props);
|
||||||
|
Object.keys(propsValue).forEach(key => {
|
||||||
|
const value = propsValue[key];
|
||||||
|
if (propsValue[key] !== undefined) {
|
||||||
|
mergedContext[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { cache } = propsValue;
|
||||||
|
mergedContext.cache = mergedContext.cache || createCache();
|
||||||
|
mergedContext.defaultCache = !cache && parentContext.value.defaultCache;
|
||||||
|
context.value = mergedContext;
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
provide(StyleContextKey, context);
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
export const styleProviderProps = () => ({
|
||||||
|
autoClear: booleanType(),
|
||||||
|
/** @private Test only. Not work in production. */
|
||||||
|
mock: stringType<'server' | 'client'>(),
|
||||||
|
/**
|
||||||
|
* Only set when you need ssr to extract style on you own.
|
||||||
|
* If not provided, it will auto create <style /> on the end of Provider in server side.
|
||||||
|
*/
|
||||||
|
cache: objectType<CacheEntity>(),
|
||||||
|
/** Tell children that this context is default generated context */
|
||||||
|
defaultCache: booleanType(),
|
||||||
|
/** Use `:where` selector to reduce hashId css selector priority */
|
||||||
|
hashPriority: stringType<HashPriority>(),
|
||||||
|
/** Tell cssinjs where to inject style in */
|
||||||
|
container: someType<Element | ShadowRoot>(),
|
||||||
|
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
|
||||||
|
ssrInline: booleanType(),
|
||||||
|
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
|
||||||
|
transformers: arrayType<Transformer[]>(),
|
||||||
|
/**
|
||||||
|
* Linters to lint css before inject in document.
|
||||||
|
* Styles will be linted after transforming.
|
||||||
|
* Please note that `linters` do not support dynamic update.
|
||||||
|
*/
|
||||||
|
linters: arrayType<Linter[]>(),
|
||||||
|
});
|
||||||
|
export type StyleProviderProps = Partial<ExtractPropTypes<ReturnType<typeof styleProviderProps>>>;
|
||||||
|
export const StyleProvider = withInstall(
|
||||||
|
defineComponent({
|
||||||
|
name: 'AStyleProvider',
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: initDefaultProps(styleProviderProps(), defaultStyleContext),
|
||||||
|
setup(props, { slots }) {
|
||||||
|
useStyleProvider(props);
|
||||||
|
return () => slots.default?.();
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
useStyleInject,
|
||||||
|
useStyleProvider,
|
||||||
|
StyleProvider,
|
||||||
|
};
|
|
@ -0,0 +1,128 @@
|
||||||
|
import hash from '@emotion/hash';
|
||||||
|
import { ATTR_TOKEN, CSS_IN_JS_INSTANCE, CSS_IN_JS_INSTANCE_ID } from '../StyleContext';
|
||||||
|
import type Theme from '../theme/Theme';
|
||||||
|
import useGlobalCache from './useGlobalCache';
|
||||||
|
import { flattenToken, token2key } from '../util';
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
|
const EMPTY_OVERRIDE = {};
|
||||||
|
|
||||||
|
// Generate different prefix to make user selector break in production env.
|
||||||
|
// This helps developer not to do style override directly on the hash id.
|
||||||
|
const hashPrefix = process.env.NODE_ENV !== 'production' ? 'css-dev-only-do-not-override' : 'css';
|
||||||
|
|
||||||
|
export interface Option<DerivativeToken> {
|
||||||
|
/**
|
||||||
|
* Generate token with salt.
|
||||||
|
* This is used to generate different hashId even same derivative token for different version.
|
||||||
|
*/
|
||||||
|
salt?: string;
|
||||||
|
override?: object;
|
||||||
|
/**
|
||||||
|
* Format token as you need. Such as:
|
||||||
|
*
|
||||||
|
* - rename token
|
||||||
|
* - merge token
|
||||||
|
* - delete token
|
||||||
|
*
|
||||||
|
* This should always be the same since it's one time process.
|
||||||
|
* It's ok to useMemo outside but this has better cache strategy.
|
||||||
|
*/
|
||||||
|
formatToken?: (mergedToken: any) => DerivativeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokenKeys = new Map<string, number>();
|
||||||
|
function recordCleanToken(tokenKey: string) {
|
||||||
|
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStyleTags(key: string) {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
const styles = document.querySelectorAll(`style[${ATTR_TOKEN}="${key}"]`);
|
||||||
|
|
||||||
|
styles.forEach(style => {
|
||||||
|
if ((style as any)[CSS_IN_JS_INSTANCE] === CSS_IN_JS_INSTANCE_ID) {
|
||||||
|
style.parentNode?.removeChild(style);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove will check current keys first
|
||||||
|
function cleanTokenStyle(tokenKey: string) {
|
||||||
|
tokenKeys.set(tokenKey, (tokenKeys.get(tokenKey) || 0) - 1);
|
||||||
|
|
||||||
|
const tokenKeyList = Array.from(tokenKeys.keys());
|
||||||
|
const cleanableKeyList = tokenKeyList.filter(key => {
|
||||||
|
const count = tokenKeys.get(key) || 0;
|
||||||
|
|
||||||
|
return count <= 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cleanableKeyList.length < tokenKeyList.length) {
|
||||||
|
cleanableKeyList.forEach(key => {
|
||||||
|
removeStyleTags(key);
|
||||||
|
tokenKeys.delete(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache theme derivative token as global shared one
|
||||||
|
* @param theme Theme entity
|
||||||
|
* @param tokens List of tokens, used for cache. Please do not dynamic generate object directly
|
||||||
|
* @param option Additional config
|
||||||
|
* @returns Call Theme.getDerivativeToken(tokenObject) to get token
|
||||||
|
*/
|
||||||
|
export default function useCacheToken<DerivativeToken = object, DesignToken = DerivativeToken>(
|
||||||
|
theme: Ref<Theme<any, any>>,
|
||||||
|
tokens: Ref<Partial<DesignToken>[]>,
|
||||||
|
option: Ref<Option<DerivativeToken>> = ref({}),
|
||||||
|
) {
|
||||||
|
// Basic - We do basic cache here
|
||||||
|
const mergedToken = computed(() => Object.assign({}, ...tokens.value));
|
||||||
|
const tokenStr = computed(() => flattenToken(mergedToken.value));
|
||||||
|
const overrideTokenStr = computed(() => flattenToken(option.value.override || EMPTY_OVERRIDE));
|
||||||
|
|
||||||
|
const cachedToken = useGlobalCache<[DerivativeToken & { _tokenKey: string }, string]>(
|
||||||
|
'token',
|
||||||
|
computed(() => [
|
||||||
|
option.value.salt || '',
|
||||||
|
theme.value.id,
|
||||||
|
tokenStr.value,
|
||||||
|
overrideTokenStr.value,
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
const { salt = '', override = EMPTY_OVERRIDE, formatToken } = option.value;
|
||||||
|
const derivativeToken = theme.value.getDerivativeToken(mergedToken.value);
|
||||||
|
|
||||||
|
// Merge with override
|
||||||
|
let mergedDerivativeToken = {
|
||||||
|
...derivativeToken,
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Format if needed
|
||||||
|
if (formatToken) {
|
||||||
|
mergedDerivativeToken = formatToken(mergedDerivativeToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize for `useStyleRegister` performance
|
||||||
|
const tokenKey = token2key(mergedDerivativeToken, salt);
|
||||||
|
mergedDerivativeToken._tokenKey = tokenKey;
|
||||||
|
recordCleanToken(tokenKey);
|
||||||
|
|
||||||
|
const hashId = `${hashPrefix}-${hash(tokenKey)}`;
|
||||||
|
mergedDerivativeToken._hashId = hashId; // Not used
|
||||||
|
|
||||||
|
return [mergedDerivativeToken, hashId];
|
||||||
|
},
|
||||||
|
cache => {
|
||||||
|
// Remove token will remove all related style
|
||||||
|
cleanTokenStyle(cache[0]._tokenKey);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return cachedToken;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { useStyleInject } from '../StyleContext';
|
||||||
|
import type { KeyType } from '../Cache';
|
||||||
|
import useHMR from './useHMR';
|
||||||
|
import type { ShallowRef, Ref } from 'vue';
|
||||||
|
import { onBeforeUnmount, watch, watchEffect, shallowRef } from 'vue';
|
||||||
|
export default function useClientCache<CacheType>(
|
||||||
|
prefix: string,
|
||||||
|
keyPath: Ref<KeyType[]>,
|
||||||
|
cacheFn: () => CacheType,
|
||||||
|
onCacheRemove?: (cache: CacheType, fromHMR: boolean) => void,
|
||||||
|
): ShallowRef<CacheType> {
|
||||||
|
const styleContext = useStyleInject();
|
||||||
|
const fullPathStr = shallowRef('');
|
||||||
|
const res = shallowRef<CacheType>();
|
||||||
|
watchEffect(() => {
|
||||||
|
fullPathStr.value = [prefix, ...keyPath.value].join('%');
|
||||||
|
});
|
||||||
|
const HMRUpdate = useHMR();
|
||||||
|
const clearCache = (pathStr: string) => {
|
||||||
|
styleContext.value.cache.update(pathStr, prevCache => {
|
||||||
|
const [times = 0, cache] = prevCache || [];
|
||||||
|
const nextCount = times - 1;
|
||||||
|
if (nextCount === 0) {
|
||||||
|
onCacheRemove?.(cache, false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [times - 1, cache];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
fullPathStr,
|
||||||
|
(newStr, oldStr) => {
|
||||||
|
if (oldStr) clearCache(oldStr);
|
||||||
|
// Create cache
|
||||||
|
styleContext.value.cache.update(newStr, prevCache => {
|
||||||
|
const [times = 0, cache] = prevCache || [];
|
||||||
|
|
||||||
|
// HMR should always ignore cache since developer may change it
|
||||||
|
let tmpCache = cache;
|
||||||
|
if (process.env.NODE_ENV !== 'production' && cache && HMRUpdate) {
|
||||||
|
onCacheRemove?.(tmpCache, HMRUpdate);
|
||||||
|
tmpCache = null;
|
||||||
|
}
|
||||||
|
const mergedCache = tmpCache || cacheFn();
|
||||||
|
|
||||||
|
return [times + 1, mergedCache];
|
||||||
|
});
|
||||||
|
res.value = styleContext.value.cache.get(fullPathStr.value)![1];
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearCache(fullPathStr.value);
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
function useProdHMR() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let webpackHMR = false;
|
||||||
|
|
||||||
|
function useDevHMR() {
|
||||||
|
return webpackHMR;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default process.env.NODE_ENV === 'production' ? useProdHMR : useDevHMR;
|
||||||
|
|
||||||
|
// Webpack `module.hot.accept` do not support any deps update trigger
|
||||||
|
// We have to hack handler to force mark as HRM
|
||||||
|
if (
|
||||||
|
process.env.NODE_ENV !== 'production' &&
|
||||||
|
typeof module !== 'undefined' &&
|
||||||
|
module &&
|
||||||
|
(module as any).hot
|
||||||
|
) {
|
||||||
|
const win = window as any;
|
||||||
|
if (typeof win.webpackHotUpdate === 'function') {
|
||||||
|
const originWebpackHotUpdate = win.webpackHotUpdate;
|
||||||
|
|
||||||
|
win.webpackHotUpdate = (...args: any[]) => {
|
||||||
|
webpackHMR = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
webpackHMR = false;
|
||||||
|
}, 0);
|
||||||
|
return originWebpackHotUpdate(...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,417 @@
|
||||||
|
import hash from '@emotion/hash';
|
||||||
|
import type * as CSS from 'csstype';
|
||||||
|
// @ts-ignore
|
||||||
|
import unitless from '@emotion/unitless';
|
||||||
|
import { compile, serialize, stringify } from 'stylis';
|
||||||
|
import type { Theme, Transformer } from '..';
|
||||||
|
import type Cache from '../Cache';
|
||||||
|
import type Keyframes from '../Keyframes';
|
||||||
|
import type { Linter } from '../linters';
|
||||||
|
import { contentQuotesLinter, hashedAnimationLinter } from '../linters';
|
||||||
|
import type { HashPriority } from '../StyleContext';
|
||||||
|
import {
|
||||||
|
useStyleInject,
|
||||||
|
ATTR_DEV_CACHE_PATH,
|
||||||
|
ATTR_MARK,
|
||||||
|
ATTR_TOKEN,
|
||||||
|
CSS_IN_JS_INSTANCE,
|
||||||
|
CSS_IN_JS_INSTANCE_ID,
|
||||||
|
} from '../StyleContext';
|
||||||
|
import { supportLayer } from '../util';
|
||||||
|
import useGlobalCache from './useGlobalCache';
|
||||||
|
import canUseDom from '../../canUseDom';
|
||||||
|
import { removeCSS, updateCSS } from '../../../vc-util/Dom/dynamicCSS';
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import type { VueNode } from '../../type';
|
||||||
|
|
||||||
|
const isClientSide = canUseDom();
|
||||||
|
|
||||||
|
const SKIP_CHECK = '_skip_check_';
|
||||||
|
|
||||||
|
export type CSSProperties = Omit<CSS.PropertiesFallback<number | string>, 'animationName'> & {
|
||||||
|
animationName?: CSS.PropertiesFallback<number | string>['animationName'] | Keyframes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CSSPropertiesWithMultiValues = {
|
||||||
|
[K in keyof CSSProperties]:
|
||||||
|
| CSSProperties[K]
|
||||||
|
| Extract<CSSProperties[K], string>[]
|
||||||
|
| {
|
||||||
|
[SKIP_CHECK]: boolean;
|
||||||
|
value: CSSProperties[K] | Extract<CSSProperties[K], string>[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CSSPseudos = { [K in CSS.Pseudos]?: CSSObject };
|
||||||
|
|
||||||
|
type ArrayCSSInterpolation = CSSInterpolation[];
|
||||||
|
|
||||||
|
export type InterpolationPrimitive = null | undefined | boolean | number | string | CSSObject;
|
||||||
|
|
||||||
|
export type CSSInterpolation = InterpolationPrimitive | ArrayCSSInterpolation | Keyframes;
|
||||||
|
|
||||||
|
export type CSSOthersObject = Record<string, CSSInterpolation>;
|
||||||
|
|
||||||
|
export interface CSSObject extends CSSPropertiesWithMultiValues, CSSPseudos, CSSOthersObject {}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// == Parser ==
|
||||||
|
// ============================================================================
|
||||||
|
// Preprocessor style content to browser support one
|
||||||
|
export function normalizeStyle(styleStr: string) {
|
||||||
|
const serialized = serialize(compile(styleStr), stringify);
|
||||||
|
return serialized.replace(/\{%%%\:[^;];}/g, ';');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCompoundCSSProperty(value: CSSObject[string]) {
|
||||||
|
return typeof value === 'object' && value && SKIP_CHECK in value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注入 hash 值
|
||||||
|
function injectSelectorHash(key: string, hashId: string, hashPriority?: HashPriority) {
|
||||||
|
if (!hashId) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashClassName = `.${hashId}`;
|
||||||
|
const hashSelector = hashPriority === 'low' ? `:where(${hashClassName})` : hashClassName;
|
||||||
|
|
||||||
|
// 注入 hashId
|
||||||
|
const keys = key.split(',').map(k => {
|
||||||
|
const fullPath = k.trim().split(/\s+/);
|
||||||
|
|
||||||
|
// 如果 Selector 第一个是 HTML Element,那我们就插到它的后面。反之,就插到最前面。
|
||||||
|
let firstPath = fullPath[0] || '';
|
||||||
|
const htmlElement = firstPath.match(/^\w+/)?.[0] || '';
|
||||||
|
|
||||||
|
firstPath = `${htmlElement}${hashSelector}${firstPath.slice(htmlElement.length)}`;
|
||||||
|
|
||||||
|
return [firstPath, ...fullPath.slice(1)].join(' ');
|
||||||
|
});
|
||||||
|
return keys.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParseConfig {
|
||||||
|
hashId?: string;
|
||||||
|
hashPriority?: HashPriority;
|
||||||
|
layer?: string;
|
||||||
|
path?: string;
|
||||||
|
transformers?: Transformer[];
|
||||||
|
linters?: Linter[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParseInfo {
|
||||||
|
root?: boolean;
|
||||||
|
injectHash?: boolean;
|
||||||
|
parentSelectors: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global effect style will mount once and not removed
|
||||||
|
// The effect will not save in SSR cache (e.g. keyframes)
|
||||||
|
const globalEffectStyleKeys = new Set();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private Test only. Clear the global effect style keys.
|
||||||
|
*/
|
||||||
|
export const _cf =
|
||||||
|
process.env.NODE_ENV !== 'production' ? () => globalEffectStyleKeys.clear() : undefined;
|
||||||
|
|
||||||
|
// Parse CSSObject to style content
|
||||||
|
export const parseStyle = (
|
||||||
|
interpolation: CSSInterpolation,
|
||||||
|
config: ParseConfig = {},
|
||||||
|
{ root, injectHash, parentSelectors }: ParseInfo = {
|
||||||
|
root: true,
|
||||||
|
parentSelectors: [],
|
||||||
|
},
|
||||||
|
): [
|
||||||
|
parsedStr: string,
|
||||||
|
// Style content which should be unique on all of the style (e.g. Keyframes).
|
||||||
|
// Firefox will flick with same animation name when exist multiple same keyframes.
|
||||||
|
effectStyle: Record<string, string>,
|
||||||
|
] => {
|
||||||
|
const { hashId, layer, path, hashPriority, transformers = [], linters = [] } = config;
|
||||||
|
let styleStr = '';
|
||||||
|
let effectStyle: Record<string, string> = {};
|
||||||
|
|
||||||
|
function parseKeyframes(keyframes: Keyframes) {
|
||||||
|
const animationName = keyframes.getName(hashId);
|
||||||
|
if (!effectStyle[animationName]) {
|
||||||
|
const [parsedStr] = parseStyle(keyframes.style, config, {
|
||||||
|
root: false,
|
||||||
|
parentSelectors,
|
||||||
|
});
|
||||||
|
|
||||||
|
effectStyle[animationName] = `@keyframes ${keyframes.getName(hashId)}${parsedStr}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenList(list: ArrayCSSInterpolation, fullList: CSSObject[] = []) {
|
||||||
|
list.forEach(item => {
|
||||||
|
if (Array.isArray(item)) {
|
||||||
|
flattenList(item, fullList);
|
||||||
|
} else if (item) {
|
||||||
|
fullList.push(item as CSSObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fullList;
|
||||||
|
}
|
||||||
|
|
||||||
|
const flattenStyleList = flattenList(
|
||||||
|
Array.isArray(interpolation) ? interpolation : [interpolation],
|
||||||
|
);
|
||||||
|
|
||||||
|
flattenStyleList.forEach(originStyle => {
|
||||||
|
// Only root level can use raw string
|
||||||
|
const style: CSSObject = typeof originStyle === 'string' && !root ? {} : originStyle;
|
||||||
|
|
||||||
|
if (typeof style === 'string') {
|
||||||
|
styleStr += `${style}\n`;
|
||||||
|
} else if ((style as any)._keyframe) {
|
||||||
|
// Keyframe
|
||||||
|
parseKeyframes(style as unknown as Keyframes);
|
||||||
|
} else {
|
||||||
|
const mergedStyle = transformers.reduce((prev, trans) => trans?.visit?.(prev) || prev, style);
|
||||||
|
|
||||||
|
// Normal CSSObject
|
||||||
|
Object.keys(mergedStyle).forEach(key => {
|
||||||
|
const value = mergedStyle[key];
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof value === 'object' &&
|
||||||
|
value &&
|
||||||
|
(key !== 'animationName' || !(value as Keyframes)._keyframe) &&
|
||||||
|
!isCompoundCSSProperty(value)
|
||||||
|
) {
|
||||||
|
let subInjectHash = false;
|
||||||
|
|
||||||
|
// 当成嵌套对象来处理
|
||||||
|
let mergedKey = key.trim();
|
||||||
|
// Whether treat child as root. In most case it is false.
|
||||||
|
let nextRoot = false;
|
||||||
|
|
||||||
|
// 拆分多个选择器
|
||||||
|
if ((root || injectHash) && hashId) {
|
||||||
|
if (mergedKey.startsWith('@')) {
|
||||||
|
// 略过媒体查询,交给子节点继续插入 hashId
|
||||||
|
subInjectHash = true;
|
||||||
|
} else {
|
||||||
|
// 注入 hashId
|
||||||
|
mergedKey = injectSelectorHash(key, hashId, hashPriority);
|
||||||
|
}
|
||||||
|
} else if (root && !hashId && (mergedKey === '&' || mergedKey === '')) {
|
||||||
|
// In case of `{ '&': { a: { color: 'red' } } }` or `{ '': { a: { color: 'red' } } }` without hashId,
|
||||||
|
// we will get `&{a:{color:red;}}` or `{a:{color:red;}}` string for stylis to compile.
|
||||||
|
// But it does not conform to stylis syntax,
|
||||||
|
// and finally we will get `{color:red;}` as css, which is wrong.
|
||||||
|
// So we need to remove key in root, and treat child `{ a: { color: 'red' } }` as root.
|
||||||
|
mergedKey = '';
|
||||||
|
nextRoot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [parsedStr, childEffectStyle] = parseStyle(value as any, config, {
|
||||||
|
root: nextRoot,
|
||||||
|
injectHash: subInjectHash,
|
||||||
|
parentSelectors: [...parentSelectors, mergedKey],
|
||||||
|
});
|
||||||
|
|
||||||
|
effectStyle = {
|
||||||
|
...effectStyle,
|
||||||
|
...childEffectStyle,
|
||||||
|
};
|
||||||
|
|
||||||
|
styleStr += `${mergedKey}${parsedStr}`;
|
||||||
|
} else {
|
||||||
|
const actualValue = (value as any)?.value ?? value;
|
||||||
|
if (
|
||||||
|
process.env.NODE_ENV !== 'production' &&
|
||||||
|
(typeof value !== 'object' || !(value as any)?.[SKIP_CHECK])
|
||||||
|
) {
|
||||||
|
[contentQuotesLinter, hashedAnimationLinter, ...linters].forEach(linter =>
|
||||||
|
linter(key, actualValue, { path, hashId, parentSelectors }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是样式则直接插入
|
||||||
|
const styleName = key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
|
||||||
|
|
||||||
|
// Auto suffix with px
|
||||||
|
let formatValue = actualValue;
|
||||||
|
if (!unitless[key] && typeof formatValue === 'number' && formatValue !== 0) {
|
||||||
|
formatValue = `${formatValue}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle animationName & Keyframe value
|
||||||
|
if (key === 'animationName' && (value as Keyframes)?._keyframe) {
|
||||||
|
parseKeyframes(value as Keyframes);
|
||||||
|
formatValue = (value as Keyframes).getName(hashId);
|
||||||
|
}
|
||||||
|
|
||||||
|
styleStr += `${styleName}:${formatValue};`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
styleStr = `{${styleStr}}`;
|
||||||
|
} else if (layer && supportLayer()) {
|
||||||
|
const layerCells = layer.split(',');
|
||||||
|
const layerName = layerCells[layerCells.length - 1].trim();
|
||||||
|
styleStr = `@layer ${layerName} {${styleStr}}`;
|
||||||
|
|
||||||
|
// Order of layer if needed
|
||||||
|
if (layerCells.length > 1) {
|
||||||
|
// zombieJ: stylis do not support layer order, so we need to handle it manually.
|
||||||
|
styleStr = `@layer ${layer}{%%%:%}${styleStr}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [styleStr, effectStyle];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// == Register ==
|
||||||
|
// ============================================================================
|
||||||
|
function uniqueHash(path: (string | number)[], styleStr: string) {
|
||||||
|
return hash(`${path.join('%')}${styleStr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function Empty() {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a style to the global style sheet.
|
||||||
|
*/
|
||||||
|
export default function useStyleRegister(
|
||||||
|
info: Ref<{
|
||||||
|
theme: Theme<any, any>;
|
||||||
|
token: any;
|
||||||
|
path: string[];
|
||||||
|
hashId?: string;
|
||||||
|
layer?: string;
|
||||||
|
}>,
|
||||||
|
styleFn: () => CSSInterpolation,
|
||||||
|
) {
|
||||||
|
const styleContext = useStyleInject();
|
||||||
|
|
||||||
|
const tokenKey = computed(() => info.value.token._tokenKey as string);
|
||||||
|
|
||||||
|
const fullPath = computed(() => [tokenKey.value, ...info.value.path]);
|
||||||
|
|
||||||
|
// Check if need insert style
|
||||||
|
let isMergedClientSide = isClientSide;
|
||||||
|
if (process.env.NODE_ENV !== 'production' && styleContext.value.mock !== undefined) {
|
||||||
|
isMergedClientSide = styleContext.value.mock === 'client';
|
||||||
|
}
|
||||||
|
|
||||||
|
// const [cacheStyle[0], cacheStyle[1], cacheStyle[2]]
|
||||||
|
useGlobalCache(
|
||||||
|
'style',
|
||||||
|
fullPath,
|
||||||
|
// Create cache if needed
|
||||||
|
() => {
|
||||||
|
const styleObj = styleFn();
|
||||||
|
const { hashPriority, container, transformers, linters } = styleContext.value;
|
||||||
|
const { path, hashId, layer } = info.value;
|
||||||
|
const [parsedStyle, effectStyle] = parseStyle(styleObj, {
|
||||||
|
hashId,
|
||||||
|
hashPriority,
|
||||||
|
layer,
|
||||||
|
path: path.join('-'),
|
||||||
|
transformers,
|
||||||
|
linters,
|
||||||
|
});
|
||||||
|
const styleStr = normalizeStyle(parsedStyle);
|
||||||
|
const styleId = uniqueHash(fullPath.value, styleStr);
|
||||||
|
|
||||||
|
if (isMergedClientSide) {
|
||||||
|
const style = updateCSS(styleStr, styleId, {
|
||||||
|
mark: ATTR_MARK,
|
||||||
|
prepend: 'queue',
|
||||||
|
attachTo: container,
|
||||||
|
});
|
||||||
|
|
||||||
|
(style as any)[CSS_IN_JS_INSTANCE] = CSS_IN_JS_INSTANCE_ID;
|
||||||
|
|
||||||
|
// Used for `useCacheToken` to remove on batch when token removed
|
||||||
|
style.setAttribute(ATTR_TOKEN, tokenKey.value);
|
||||||
|
|
||||||
|
// Dev usage to find which cache path made this easily
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
style.setAttribute(ATTR_DEV_CACHE_PATH, fullPath.value.join('|'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inject client side effect style
|
||||||
|
Object.keys(effectStyle).forEach(effectKey => {
|
||||||
|
if (!globalEffectStyleKeys.has(effectKey)) {
|
||||||
|
globalEffectStyleKeys.add(effectKey);
|
||||||
|
|
||||||
|
// Inject
|
||||||
|
updateCSS(normalizeStyle(effectStyle[effectKey]), `_effect-${effectKey}`, {
|
||||||
|
mark: ATTR_MARK,
|
||||||
|
prepend: 'queue',
|
||||||
|
attachTo: container,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return [styleStr, tokenKey.value, styleId];
|
||||||
|
},
|
||||||
|
// Remove cache if no need
|
||||||
|
([, , styleId], fromHMR) => {
|
||||||
|
if ((fromHMR || styleContext.value.autoClear) && isClientSide) {
|
||||||
|
removeCSS(styleId, { mark: ATTR_MARK });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return (node: VueNode) => {
|
||||||
|
return node;
|
||||||
|
// let styleNode: VueNode;
|
||||||
|
// if (!styleContext.ssrInline || isMergedClientSide || !styleContext.defaultCache) {
|
||||||
|
// styleNode = <Empty />;
|
||||||
|
// } else {
|
||||||
|
// styleNode = (
|
||||||
|
// <style
|
||||||
|
// {...{
|
||||||
|
// [ATTR_TOKEN]: cacheStyle.value[1],
|
||||||
|
// [ATTR_MARK]: cacheStyle.value[2],
|
||||||
|
// }}
|
||||||
|
// innerHTML={cacheStyle.value[0]}
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// {styleNode}
|
||||||
|
// {node}
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// == SSR ==
|
||||||
|
// ============================================================================
|
||||||
|
export function extractStyle(cache: Cache) {
|
||||||
|
// prefix with `style` is used for `useStyleRegister` to cache style context
|
||||||
|
const styleKeys = Array.from(cache.cache.keys()).filter(key => key.startsWith('style%'));
|
||||||
|
|
||||||
|
// const tokenStyles: Record<string, string[]> = {};
|
||||||
|
|
||||||
|
let styleText = '';
|
||||||
|
|
||||||
|
styleKeys.forEach(key => {
|
||||||
|
const [styleStr, tokenKey, styleId]: [string, string, string] = cache.cache.get(key)![1];
|
||||||
|
|
||||||
|
styleText += `<style ${ATTR_TOKEN}="${tokenKey}" ${ATTR_MARK}="${styleId}">${styleStr}</style>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return styleText;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import useCacheToken from './hooks/useCacheToken';
|
||||||
|
import type { CSSInterpolation, CSSObject } from './hooks/useStyleRegister';
|
||||||
|
import useStyleRegister, { extractStyle } from './hooks/useStyleRegister';
|
||||||
|
import Keyframes from './Keyframes';
|
||||||
|
import type { Linter } from './linters';
|
||||||
|
import { legacyNotSelectorLinter, logicalPropertiesLinter } from './linters';
|
||||||
|
import type { StyleContextProps, StyleProviderProps } from './StyleContext';
|
||||||
|
import { createCache, useStyleInject, useStyleProvider, StyleProvider } from './StyleContext';
|
||||||
|
import type { DerivativeFunc, TokenType } from './theme';
|
||||||
|
import { createTheme, Theme } from './theme';
|
||||||
|
import type { Transformer } from './transformers/interface';
|
||||||
|
import legacyLogicalPropertiesTransformer from './transformers/legacyLogicalProperties';
|
||||||
|
|
||||||
|
const cssinjs = {
|
||||||
|
Theme,
|
||||||
|
createTheme,
|
||||||
|
useStyleRegister,
|
||||||
|
useCacheToken,
|
||||||
|
createCache,
|
||||||
|
useStyleInject,
|
||||||
|
useStyleProvider,
|
||||||
|
Keyframes,
|
||||||
|
extractStyle,
|
||||||
|
|
||||||
|
// Transformer
|
||||||
|
legacyLogicalPropertiesTransformer,
|
||||||
|
|
||||||
|
// Linters
|
||||||
|
logicalPropertiesLinter,
|
||||||
|
legacyNotSelectorLinter,
|
||||||
|
|
||||||
|
// cssinjs
|
||||||
|
StyleProvider,
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
Theme,
|
||||||
|
createTheme,
|
||||||
|
useStyleRegister,
|
||||||
|
useCacheToken,
|
||||||
|
createCache,
|
||||||
|
useStyleInject,
|
||||||
|
useStyleProvider,
|
||||||
|
Keyframes,
|
||||||
|
extractStyle,
|
||||||
|
|
||||||
|
// Transformer
|
||||||
|
legacyLogicalPropertiesTransformer,
|
||||||
|
|
||||||
|
// Linters
|
||||||
|
logicalPropertiesLinter,
|
||||||
|
legacyNotSelectorLinter,
|
||||||
|
|
||||||
|
// cssinjs
|
||||||
|
StyleProvider,
|
||||||
|
};
|
||||||
|
export type {
|
||||||
|
TokenType,
|
||||||
|
CSSObject,
|
||||||
|
CSSInterpolation,
|
||||||
|
DerivativeFunc,
|
||||||
|
Transformer,
|
||||||
|
Linter,
|
||||||
|
StyleContextProps,
|
||||||
|
StyleProviderProps,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default cssinjs;
|
|
@ -0,0 +1,25 @@
|
||||||
|
import type { Linter } from './interface';
|
||||||
|
import { lintWarning } from './utils';
|
||||||
|
|
||||||
|
const linter: Linter = (key, value, info) => {
|
||||||
|
if (key === 'content') {
|
||||||
|
// From emotion: https://github.com/emotion-js/emotion/blob/main/packages/serialize/src/index.js#L63
|
||||||
|
const contentValuePattern =
|
||||||
|
/(attr|counters?|url|(((repeating-)?(linear|radial))|conic)-gradient)\(|(no-)?(open|close)-quote/;
|
||||||
|
const contentValues = ['normal', 'none', 'initial', 'inherit', 'unset'];
|
||||||
|
if (
|
||||||
|
typeof value !== 'string' ||
|
||||||
|
(contentValues.indexOf(value) === -1 &&
|
||||||
|
!contentValuePattern.test(value) &&
|
||||||
|
(value.charAt(0) !== value.charAt(value.length - 1) ||
|
||||||
|
(value.charAt(0) !== '"' && value.charAt(0) !== "'")))
|
||||||
|
) {
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using a value for 'content' without quotes, try replacing it with \`content: '"${value}"'\`.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default linter;
|
|
@ -0,0 +1,15 @@
|
||||||
|
import type { Linter } from './interface';
|
||||||
|
import { lintWarning } from './utils';
|
||||||
|
|
||||||
|
const linter: Linter = (key, value, info) => {
|
||||||
|
if (key === 'animation') {
|
||||||
|
if (info.hashId && value !== 'none') {
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using hashed animation '${value}', in which case 'animationName' with Keyframe as value is recommended.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default linter;
|
|
@ -0,0 +1,5 @@
|
||||||
|
export { default as contentQuotesLinter } from './contentQuotesLinter';
|
||||||
|
export { default as hashedAnimationLinter } from './hashedAnimationLinter';
|
||||||
|
export type { Linter } from './interface';
|
||||||
|
export { default as legacyNotSelectorLinter } from './legacyNotSelectorLinter';
|
||||||
|
export { default as logicalPropertiesLinter } from './logicalPropertiesLinter';
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface LinterInfo {
|
||||||
|
path?: string;
|
||||||
|
hashId?: string;
|
||||||
|
parentSelectors: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Linter {
|
||||||
|
(key: string, value: string | number, info: LinterInfo): void;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import type { Linter, LinterInfo } from './interface';
|
||||||
|
import { lintWarning } from './utils';
|
||||||
|
|
||||||
|
function isConcatSelector(selector: string) {
|
||||||
|
const notContent = selector.match(/:not\(([^)]*)\)/)?.[1] || '';
|
||||||
|
|
||||||
|
// split selector. e.g.
|
||||||
|
// `h1#a.b` => ['h1', #a', '.b']
|
||||||
|
const splitCells = notContent.split(/(\[[^[]*])|(?=[.#])/).filter(str => str);
|
||||||
|
|
||||||
|
return splitCells.length > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePath(info: LinterInfo) {
|
||||||
|
return info.parentSelectors.reduce((prev, cur) => {
|
||||||
|
if (!prev) {
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur.includes('&') ? cur.replace(/&/g, prev) : `${prev} ${cur}`;
|
||||||
|
}, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const linter: Linter = (_key, _value, info) => {
|
||||||
|
const parentSelectorPath = parsePath(info);
|
||||||
|
const notList = parentSelectorPath.match(/:not\([^)]*\)/g) || [];
|
||||||
|
|
||||||
|
if (notList.length > 0 && notList.some(isConcatSelector)) {
|
||||||
|
lintWarning(`Concat ':not' selector not support in legacy browsers.`, info);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default linter;
|
|
@ -0,0 +1,88 @@
|
||||||
|
import type { Linter } from './interface';
|
||||||
|
import { lintWarning } from './utils';
|
||||||
|
|
||||||
|
const linter: Linter = (key, value, info) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'marginLeft':
|
||||||
|
case 'marginRight':
|
||||||
|
case 'paddingLeft':
|
||||||
|
case 'paddingRight':
|
||||||
|
case 'left':
|
||||||
|
case 'right':
|
||||||
|
case 'borderLeft':
|
||||||
|
case 'borderLeftWidth':
|
||||||
|
case 'borderLeftStyle':
|
||||||
|
case 'borderLeftColor':
|
||||||
|
case 'borderRight':
|
||||||
|
case 'borderRightWidth':
|
||||||
|
case 'borderRightStyle':
|
||||||
|
case 'borderRightColor':
|
||||||
|
case 'borderTopLeftRadius':
|
||||||
|
case 'borderTopRightRadius':
|
||||||
|
case 'borderBottomLeftRadius':
|
||||||
|
case 'borderBottomRightRadius':
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using non-logical property '${key}' which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
case 'margin':
|
||||||
|
case 'padding':
|
||||||
|
case 'borderWidth':
|
||||||
|
case 'borderStyle':
|
||||||
|
// case 'borderColor':
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const valueArr = value.split(' ').map(item => item.trim());
|
||||||
|
if (valueArr.length === 4 && valueArr[1] !== valueArr[3]) {
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using '${key}' property with different left ${key} and right ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 'clear':
|
||||||
|
case 'textAlign':
|
||||||
|
if (value === 'left' || value === 'right') {
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 'borderRadius':
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const radiusGroups = value.split('/').map(item => item.trim());
|
||||||
|
const invalid = radiusGroups.reduce((result, group) => {
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const radiusArr = group.split(' ').map(item => item.trim());
|
||||||
|
// borderRadius: '2px 4px'
|
||||||
|
if (radiusArr.length >= 2 && radiusArr[0] !== radiusArr[1]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// borderRadius: '4px 4px 2px'
|
||||||
|
if (radiusArr.length === 3 && radiusArr[1] !== radiusArr[2]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// borderRadius: '4px 4px 2px 4px'
|
||||||
|
if (radiusArr.length === 4 && radiusArr[2] !== radiusArr[3]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if (invalid) {
|
||||||
|
lintWarning(
|
||||||
|
`You seem to be using non-logical value '${value}' of ${key}, which is not compatible with RTL mode. Please use logical properties and values instead. For more information: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties.`,
|
||||||
|
info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default linter;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import devWarning from '../../../vc-util/warning';
|
||||||
|
import type { LinterInfo } from './interface';
|
||||||
|
|
||||||
|
export function lintWarning(message: string, info: LinterInfo) {
|
||||||
|
const { path, parentSelectors } = info;
|
||||||
|
|
||||||
|
devWarning(
|
||||||
|
false,
|
||||||
|
`[Ant Design Vue CSS-in-JS] ${path ? `Error in '${path}': ` : ''}${message}${
|
||||||
|
parentSelectors.length ? ` Selector info: ${parentSelectors.join(' -> ')}` : ''
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import warning from '../../warning';
|
||||||
|
import type { DerivativeFunc, TokenType } from './interface';
|
||||||
|
|
||||||
|
let uuid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme with algorithms to derive tokens from design tokens.
|
||||||
|
* Use `createTheme` first which will help to manage the theme instance cache.
|
||||||
|
*/
|
||||||
|
export default class Theme<DesignToken extends TokenType, DerivativeToken extends TokenType> {
|
||||||
|
private derivatives: DerivativeFunc<DesignToken, DerivativeToken>[];
|
||||||
|
public readonly id: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
derivatives:
|
||||||
|
| DerivativeFunc<DesignToken, DerivativeToken>
|
||||||
|
| DerivativeFunc<DesignToken, DerivativeToken>[],
|
||||||
|
) {
|
||||||
|
this.derivatives = Array.isArray(derivatives) ? derivatives : [derivatives];
|
||||||
|
this.id = uuid;
|
||||||
|
|
||||||
|
if (derivatives.length === 0) {
|
||||||
|
warning(
|
||||||
|
derivatives.length > 0,
|
||||||
|
'[Ant Design Vue CSS-in-JS] Theme should have at least one derivative function.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDerivativeToken(token: DesignToken): DerivativeToken {
|
||||||
|
return this.derivatives.reduce<DerivativeToken>(
|
||||||
|
(result, derivative) => derivative(token, result),
|
||||||
|
undefined as any,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
import type Theme from './Theme';
|
||||||
|
import type { DerivativeFunc } from './interface';
|
||||||
|
|
||||||
|
// ================================== Cache ==================================
|
||||||
|
type ThemeCacheMap = Map<
|
||||||
|
DerivativeFunc<any, any>,
|
||||||
|
{
|
||||||
|
map?: ThemeCacheMap;
|
||||||
|
value?: [Theme<any, any>, number];
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
type DerivativeOptions = DerivativeFunc<any, any>[];
|
||||||
|
|
||||||
|
export function sameDerivativeOption(left: DerivativeOptions, right: DerivativeOptions) {
|
||||||
|
if (left.length !== right.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < left.length; i++) {
|
||||||
|
if (left[i] !== right[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ThemeCache {
|
||||||
|
public static MAX_CACHE_SIZE = 20;
|
||||||
|
public static MAX_CACHE_OFFSET = 5;
|
||||||
|
|
||||||
|
private readonly cache: ThemeCacheMap;
|
||||||
|
private keys: DerivativeOptions[];
|
||||||
|
private cacheCallTimes: number;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.cache = new Map();
|
||||||
|
this.keys = [];
|
||||||
|
this.cacheCallTimes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public size(): number {
|
||||||
|
return this.keys.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private internalGet(
|
||||||
|
derivativeOption: DerivativeOptions,
|
||||||
|
updateCallTimes = false,
|
||||||
|
): [Theme<any, any>, number] | undefined {
|
||||||
|
let cache: ReturnType<ThemeCacheMap['get']> = { map: this.cache };
|
||||||
|
derivativeOption.forEach(derivative => {
|
||||||
|
if (!cache) {
|
||||||
|
cache = undefined;
|
||||||
|
} else {
|
||||||
|
cache = cache?.map?.get(derivative);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (cache?.value && updateCallTimes) {
|
||||||
|
cache.value[1] = this.cacheCallTimes++;
|
||||||
|
}
|
||||||
|
return cache?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(derivativeOption: DerivativeOptions): Theme<any, any> | undefined {
|
||||||
|
return this.internalGet(derivativeOption, true)?.[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public has(derivativeOption: DerivativeOptions): boolean {
|
||||||
|
return !!this.internalGet(derivativeOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set(derivativeOption: DerivativeOptions, value: Theme<any, any>): void {
|
||||||
|
// New cache
|
||||||
|
if (!this.has(derivativeOption)) {
|
||||||
|
if (this.size() + 1 > ThemeCache.MAX_CACHE_SIZE + ThemeCache.MAX_CACHE_OFFSET) {
|
||||||
|
const [targetKey] = this.keys.reduce<[DerivativeOptions, number]>(
|
||||||
|
(result, key) => {
|
||||||
|
const [, callTimes] = result;
|
||||||
|
if (this.internalGet(key)![1] < callTimes) {
|
||||||
|
return [key, this.internalGet(key)![1]];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
[this.keys[0], this.cacheCallTimes],
|
||||||
|
);
|
||||||
|
this.delete(targetKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.keys.push(derivativeOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cache = this.cache;
|
||||||
|
derivativeOption.forEach((derivative, index) => {
|
||||||
|
if (index === derivativeOption.length - 1) {
|
||||||
|
cache.set(derivative, { value: [value, this.cacheCallTimes++] });
|
||||||
|
} else {
|
||||||
|
const cacheValue = cache.get(derivative);
|
||||||
|
if (!cacheValue) {
|
||||||
|
cache.set(derivative, { map: new Map() });
|
||||||
|
} else if (!cacheValue.map) {
|
||||||
|
cacheValue.map = new Map();
|
||||||
|
}
|
||||||
|
cache = cache.get(derivative)!.map!;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private deleteByPath(
|
||||||
|
currentCache: ThemeCacheMap,
|
||||||
|
derivatives: DerivativeFunc<any, any>[],
|
||||||
|
): Theme<any, any> | undefined {
|
||||||
|
const cache = currentCache.get(derivatives[0])!;
|
||||||
|
if (derivatives.length === 1) {
|
||||||
|
if (!cache.map) {
|
||||||
|
currentCache.delete(derivatives[0]);
|
||||||
|
} else {
|
||||||
|
currentCache.set(derivatives[0], { map: cache.map });
|
||||||
|
}
|
||||||
|
return cache.value?.[0];
|
||||||
|
}
|
||||||
|
const result = this.deleteByPath(cache.map!, derivatives.slice(1));
|
||||||
|
if ((!cache.map || cache.map.size === 0) && !cache.value) {
|
||||||
|
currentCache.delete(derivatives[0]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delete(derivativeOption: DerivativeOptions): Theme<any, any> | undefined {
|
||||||
|
// If cache exists
|
||||||
|
if (this.has(derivativeOption)) {
|
||||||
|
this.keys = this.keys.filter(item => !sameDerivativeOption(item, derivativeOption));
|
||||||
|
return this.deleteByPath(this.cache, derivativeOption);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import ThemeCache from './ThemeCache';
|
||||||
|
import Theme from './Theme';
|
||||||
|
import type { DerivativeFunc, TokenType } from './interface';
|
||||||
|
|
||||||
|
const cacheThemes = new ThemeCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as new Theme, but will always return same one if `derivative` not changed.
|
||||||
|
*/
|
||||||
|
export default function createTheme<
|
||||||
|
DesignToken extends TokenType,
|
||||||
|
DerivativeToken extends TokenType,
|
||||||
|
>(
|
||||||
|
derivatives:
|
||||||
|
| DerivativeFunc<DesignToken, DerivativeToken>[]
|
||||||
|
| DerivativeFunc<DesignToken, DerivativeToken>,
|
||||||
|
) {
|
||||||
|
const derivativeArr = Array.isArray(derivatives) ? derivatives : [derivatives];
|
||||||
|
// Create new theme if not exist
|
||||||
|
if (!cacheThemes.has(derivativeArr)) {
|
||||||
|
cacheThemes.set(derivativeArr, new Theme(derivativeArr));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get theme from cache and return
|
||||||
|
return cacheThemes.get(derivativeArr)!;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export { default as createTheme } from './createTheme';
|
||||||
|
export { default as Theme } from './Theme';
|
||||||
|
export { default as ThemeCache } from './ThemeCache';
|
||||||
|
export type { TokenType, DerivativeFunc } from './interface';
|
|
@ -0,0 +1,5 @@
|
||||||
|
export type TokenType = object;
|
||||||
|
export type DerivativeFunc<DesignToken extends TokenType, DerivativeToken extends TokenType> = (
|
||||||
|
designToken: DesignToken,
|
||||||
|
derivativeToken?: DerivativeToken,
|
||||||
|
) => DerivativeToken;
|
|
@ -0,0 +1,5 @@
|
||||||
|
import type { CSSObject } from '..';
|
||||||
|
|
||||||
|
export interface Transformer {
|
||||||
|
visit?: (cssObj: CSSObject) => CSSObject;
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
import type { CSSObject } from '..';
|
||||||
|
import type { Transformer } from './interface';
|
||||||
|
|
||||||
|
function splitValues(value: string | number) {
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return [value];
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitStyle = String(value).split(/\s+/);
|
||||||
|
|
||||||
|
// Combine styles split in brackets, like `calc(1px + 2px)`
|
||||||
|
let temp = '';
|
||||||
|
let brackets = 0;
|
||||||
|
return splitStyle.reduce<string[]>((list, item) => {
|
||||||
|
if (item.includes('(')) {
|
||||||
|
temp += item;
|
||||||
|
brackets += item.split('(').length - 1;
|
||||||
|
} else if (item.includes(')')) {
|
||||||
|
temp += ` ${item}`;
|
||||||
|
brackets -= item.split(')').length - 1;
|
||||||
|
if (brackets === 0) {
|
||||||
|
list.push(temp);
|
||||||
|
temp = '';
|
||||||
|
}
|
||||||
|
} else if (brackets > 0) {
|
||||||
|
temp += ` ${item}`;
|
||||||
|
} else {
|
||||||
|
list.push(item);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
type MatchValue = string[] & {
|
||||||
|
notSplit?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function noSplit(list: MatchValue): MatchValue {
|
||||||
|
list.notSplit = true;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyMap: Record<string, MatchValue> = {
|
||||||
|
// Inset
|
||||||
|
inset: ['top', 'right', 'bottom', 'left'],
|
||||||
|
insetBlock: ['top', 'bottom'],
|
||||||
|
insetBlockStart: ['top'],
|
||||||
|
insetBlockEnd: ['bottom'],
|
||||||
|
insetInline: ['left', 'right'],
|
||||||
|
insetInlineStart: ['left'],
|
||||||
|
insetInlineEnd: ['right'],
|
||||||
|
|
||||||
|
// Margin
|
||||||
|
marginBlock: ['marginTop', 'marginBottom'],
|
||||||
|
marginBlockStart: ['marginTop'],
|
||||||
|
marginBlockEnd: ['marginBottom'],
|
||||||
|
marginInline: ['marginLeft', 'marginRight'],
|
||||||
|
marginInlineStart: ['marginLeft'],
|
||||||
|
marginInlineEnd: ['marginRight'],
|
||||||
|
|
||||||
|
// Padding
|
||||||
|
paddingBlock: ['paddingTop', 'paddingBottom'],
|
||||||
|
paddingBlockStart: ['paddingTop'],
|
||||||
|
paddingBlockEnd: ['paddingBottom'],
|
||||||
|
paddingInline: ['paddingLeft', 'paddingRight'],
|
||||||
|
paddingInlineStart: ['paddingLeft'],
|
||||||
|
paddingInlineEnd: ['paddingRight'],
|
||||||
|
|
||||||
|
// Border
|
||||||
|
borderBlock: noSplit(['borderTop', 'borderBottom']),
|
||||||
|
borderBlockStart: noSplit(['borderTop']),
|
||||||
|
borderBlockEnd: noSplit(['borderBottom']),
|
||||||
|
borderInline: noSplit(['borderLeft', 'borderRight']),
|
||||||
|
borderInlineStart: noSplit(['borderLeft']),
|
||||||
|
borderInlineEnd: noSplit(['borderRight']),
|
||||||
|
|
||||||
|
// Border width
|
||||||
|
borderBlockWidth: ['borderTopWidth', 'borderBottomWidth'],
|
||||||
|
borderBlockStartWidth: ['borderTopWidth'],
|
||||||
|
borderBlockEndWidth: ['borderBottomWidth'],
|
||||||
|
borderInlineWidth: ['borderLeftWidth', 'borderRightWidth'],
|
||||||
|
borderInlineStartWidth: ['borderLeftWidth'],
|
||||||
|
borderInlineEndWidth: ['borderRightWidth'],
|
||||||
|
|
||||||
|
// Border style
|
||||||
|
borderBlockStyle: ['borderTopStyle', 'borderBottomStyle'],
|
||||||
|
borderBlockStartStyle: ['borderTopStyle'],
|
||||||
|
borderBlockEndStyle: ['borderBottomStyle'],
|
||||||
|
borderInlineStyle: ['borderLeftStyle', 'borderRightStyle'],
|
||||||
|
borderInlineStartStyle: ['borderLeftStyle'],
|
||||||
|
borderInlineEndStyle: ['borderRightStyle'],
|
||||||
|
|
||||||
|
// Border color
|
||||||
|
borderBlockColor: ['borderTopColor', 'borderBottomColor'],
|
||||||
|
borderBlockStartColor: ['borderTopColor'],
|
||||||
|
borderBlockEndColor: ['borderBottomColor'],
|
||||||
|
borderInlineColor: ['borderLeftColor', 'borderRightColor'],
|
||||||
|
borderInlineStartColor: ['borderLeftColor'],
|
||||||
|
borderInlineEndColor: ['borderRightColor'],
|
||||||
|
|
||||||
|
// Border radius
|
||||||
|
borderStartStartRadius: ['borderTopLeftRadius'],
|
||||||
|
borderStartEndRadius: ['borderTopRightRadius'],
|
||||||
|
borderEndStartRadius: ['borderBottomLeftRadius'],
|
||||||
|
borderEndEndRadius: ['borderBottomRightRadius'],
|
||||||
|
};
|
||||||
|
|
||||||
|
function skipCheck(value: string | number) {
|
||||||
|
return { _skip_check_: true, value };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert css logical properties to legacy properties.
|
||||||
|
* Such as: `margin-block-start` to `margin-top`.
|
||||||
|
* Transform list:
|
||||||
|
* - inset
|
||||||
|
* - margin
|
||||||
|
* - padding
|
||||||
|
* - border
|
||||||
|
*/
|
||||||
|
const transform: Transformer = {
|
||||||
|
visit: cssObj => {
|
||||||
|
const clone: CSSObject = {};
|
||||||
|
|
||||||
|
Object.keys(cssObj).forEach(key => {
|
||||||
|
const value = cssObj[key];
|
||||||
|
const matchValue = keyMap[key];
|
||||||
|
|
||||||
|
if (matchValue && (typeof value === 'number' || typeof value === 'string')) {
|
||||||
|
const values = splitValues(value);
|
||||||
|
|
||||||
|
if (matchValue.length && matchValue.notSplit) {
|
||||||
|
// not split means always give same value like border
|
||||||
|
matchValue.forEach(matchKey => {
|
||||||
|
clone[matchKey] = skipCheck(value);
|
||||||
|
});
|
||||||
|
} else if (matchValue.length === 1) {
|
||||||
|
// Handle like `marginBlockStart` => `marginTop`
|
||||||
|
clone[matchValue[0]] = skipCheck(value);
|
||||||
|
} else if (matchValue.length === 2) {
|
||||||
|
// Handle like `marginBlock` => `marginTop` & `marginBottom`
|
||||||
|
matchValue.forEach((matchKey, index) => {
|
||||||
|
clone[matchKey] = skipCheck(values[index] ?? values[0]);
|
||||||
|
});
|
||||||
|
} else if (matchValue.length === 4) {
|
||||||
|
// Handle like `inset` => `top` & `right` & `bottom` & `left`
|
||||||
|
matchValue.forEach((matchKey, index) => {
|
||||||
|
clone[matchKey] = skipCheck(values[index] ?? values[index - 2] ?? values[0]);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
clone[key] = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clone[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default transform;
|
|
@ -0,0 +1,68 @@
|
||||||
|
import hash from '@emotion/hash';
|
||||||
|
import { removeCSS, updateCSS } from '../../vc-util/Dom/dynamicCSS';
|
||||||
|
import canUseDom from '../canUseDom';
|
||||||
|
|
||||||
|
export function flattenToken(token: any) {
|
||||||
|
let str = '';
|
||||||
|
Object.keys(token).forEach(key => {
|
||||||
|
const value = token[key];
|
||||||
|
str += key;
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
str += flattenToken(value);
|
||||||
|
} else {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert derivative token to key string
|
||||||
|
*/
|
||||||
|
export function token2key(token: any, salt: string): string {
|
||||||
|
return hash(`${salt}_${flattenToken(token)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const layerKey = `layer-${Date.now()}-${Math.random()}`.replace(/\./g, '');
|
||||||
|
const layerWidth = '903px';
|
||||||
|
|
||||||
|
function supportSelector(styleStr: string, handleElement?: (ele: HTMLElement) => void): boolean {
|
||||||
|
if (canUseDom()) {
|
||||||
|
updateCSS(styleStr, layerKey);
|
||||||
|
|
||||||
|
const ele = document.createElement('div');
|
||||||
|
ele.style.position = 'fixed';
|
||||||
|
ele.style.left = '0';
|
||||||
|
ele.style.top = '0';
|
||||||
|
handleElement?.(ele);
|
||||||
|
document.body.appendChild(ele);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
ele.innerHTML = 'Test';
|
||||||
|
ele.style.zIndex = '9999999';
|
||||||
|
}
|
||||||
|
|
||||||
|
const support = getComputedStyle(ele).width === layerWidth;
|
||||||
|
|
||||||
|
ele.parentNode?.removeChild(ele);
|
||||||
|
removeCSS(layerKey);
|
||||||
|
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let canLayer: boolean | undefined = undefined;
|
||||||
|
export function supportLayer(): boolean {
|
||||||
|
if (canLayer === undefined) {
|
||||||
|
canLayer = supportSelector(
|
||||||
|
`@layer ${layerKey} { .${layerKey} { width: ${layerWidth}!important; } }`,
|
||||||
|
ele => {
|
||||||
|
ele.className = layerKey;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return canLayer!;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
type RecordType = Record<string, any>;
|
||||||
|
|
||||||
|
function extendsObject<T extends RecordType>(...list: T[]) {
|
||||||
|
const result: RecordType = { ...list[0] };
|
||||||
|
|
||||||
|
for (let i = 1; i < list.length; i++) {
|
||||||
|
const obj = list[i];
|
||||||
|
if (obj) {
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
const val = obj[key];
|
||||||
|
if (val !== undefined) {
|
||||||
|
result[key] = val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default extendsObject;
|
|
@ -1,30 +0,0 @@
|
||||||
export function getComponentLocale(props, context, componentName, getDefaultLocale) {
|
|
||||||
let locale = {};
|
|
||||||
if (context && context.antLocale && context.antLocale[componentName]) {
|
|
||||||
locale = context.antLocale[componentName];
|
|
||||||
} else {
|
|
||||||
const defaultLocale = getDefaultLocale();
|
|
||||||
// TODO: make default lang of antd be English
|
|
||||||
// https://github.com/ant-design/ant-design/issues/6334
|
|
||||||
locale = defaultLocale.default || defaultLocale;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
...locale,
|
|
||||||
...props.locale,
|
|
||||||
};
|
|
||||||
result.lang = {
|
|
||||||
...locale.lang,
|
|
||||||
...props.locale.lang,
|
|
||||||
};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getLocaleCode(context) {
|
|
||||||
const localeCode = context.antLocale && context.antLocale.locale;
|
|
||||||
// Had use LocaleProvide but didn't set locale
|
|
||||||
if (context.antLocale && context.antLocale.exist && !localeCode) {
|
|
||||||
return 'zh-cn';
|
|
||||||
}
|
|
||||||
return localeCode;
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
export function isWindow(obj: any) {
|
export function isWindow(obj: any): obj is Window {
|
||||||
return obj !== null && obj !== undefined && obj === obj.window;
|
return obj !== null && obj !== undefined && obj === obj.window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,16 +12,22 @@ export default function getScroll(
|
||||||
const method = top ? 'scrollTop' : 'scrollLeft';
|
const method = top ? 'scrollTop' : 'scrollLeft';
|
||||||
let result = 0;
|
let result = 0;
|
||||||
if (isWindow(target)) {
|
if (isWindow(target)) {
|
||||||
result = (target as Window)[top ? 'pageYOffset' : 'pageXOffset'];
|
result = target[top ? 'pageYOffset' : 'pageXOffset'];
|
||||||
} else if (target instanceof Document) {
|
} else if (target instanceof Document) {
|
||||||
result = target.documentElement[method];
|
result = target.documentElement[method];
|
||||||
|
} else if (target instanceof HTMLElement) {
|
||||||
|
result = target[method];
|
||||||
} else if (target) {
|
} else if (target) {
|
||||||
result = (target as HTMLElement)[method];
|
// According to the type inference, the `target` is `never` type.
|
||||||
|
// Since we configured the loose mode type checking, and supports mocking the target with such shape below::
|
||||||
|
// `{ documentElement: { scrollLeft: 200, scrollTop: 400 } }`,
|
||||||
|
// the program may falls into this branch.
|
||||||
|
// Check the corresponding tests for details. Don't sure what is the real scenario this happens.
|
||||||
|
result = target[method];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target && !isWindow(target) && typeof result !== 'number') {
|
if (target && !isWindow(target) && typeof result !== 'number') {
|
||||||
result = ((target as HTMLElement).ownerDocument || (target as Document)).documentElement?.[
|
result = ((target.ownerDocument ?? target) as any).documentElement?.[method];
|
||||||
method
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ref, watch } from 'vue';
|
import { shallowRef, watch } from 'vue';
|
||||||
import type { MaybeComputedElementRef } from './unrefElement';
|
import type { MaybeComputedElementRef } from './unrefElement';
|
||||||
import type { UseResizeObserverOptions } from './useResizeObserver';
|
import type { UseResizeObserverOptions } from './useResizeObserver';
|
||||||
import { useResizeObserver } from './useResizeObserver';
|
import { useResizeObserver } from './useResizeObserver';
|
||||||
|
@ -23,8 +23,8 @@ export function useElementSize(
|
||||||
options: UseResizeObserverOptions = {},
|
options: UseResizeObserverOptions = {},
|
||||||
) {
|
) {
|
||||||
const { box = 'content-box' } = options;
|
const { box = 'content-box' } = options;
|
||||||
const width = ref(initialSize.width);
|
const width = shallowRef(initialSize.width);
|
||||||
const height = ref(initialSize.height);
|
const height = shallowRef(initialSize.height);
|
||||||
|
|
||||||
useResizeObserver(
|
useResizeObserver(
|
||||||
target,
|
target,
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { tryOnScopeDispose } from './tryOnScopeDispose';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
import type { MaybeElementRef } from './unrefElement';
|
||||||
|
import { unrefElement } from './unrefElement';
|
||||||
|
import { useSupported } from './useSupported';
|
||||||
|
import type { ConfigurableWindow } from './_configurable';
|
||||||
|
import { defaultWindow } from './_configurable';
|
||||||
|
|
||||||
|
export interface UseMutationObserverOptions extends MutationObserverInit, ConfigurableWindow {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch for changes being made to the DOM tree.
|
||||||
|
*
|
||||||
|
* @see https://vueuse.org/useMutationObserver
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver MutationObserver MDN
|
||||||
|
* @param target
|
||||||
|
* @param callback
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export function useMutationObserver(
|
||||||
|
target: MaybeElementRef,
|
||||||
|
callback: MutationCallback,
|
||||||
|
options: UseMutationObserverOptions = {},
|
||||||
|
) {
|
||||||
|
const { window = defaultWindow, ...mutationOptions } = options;
|
||||||
|
let observer: MutationObserver | undefined;
|
||||||
|
const isSupported = useSupported(() => window && 'MutationObserver' in window);
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
if (observer) {
|
||||||
|
observer.disconnect();
|
||||||
|
observer = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopWatch = watch(
|
||||||
|
() => unrefElement(target),
|
||||||
|
el => {
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
if (isSupported.value && window && el) {
|
||||||
|
observer = new MutationObserver(callback);
|
||||||
|
observer!.observe(el, mutationOptions);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const stop = () => {
|
||||||
|
cleanup();
|
||||||
|
stopWatch();
|
||||||
|
};
|
||||||
|
|
||||||
|
tryOnScopeDispose(stop);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isSupported,
|
||||||
|
stop,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UseMutationObserverReturn = ReturnType<typeof useMutationObserver>;
|
|
@ -1,9 +1,8 @@
|
||||||
import { tryOnMounted } from './tryOnMounted';
|
import { tryOnMounted } from './tryOnMounted';
|
||||||
import type { Ref } from 'vue';
|
import { shallowRef } from 'vue';
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
export function useSupported(callback: () => unknown, sync = false) {
|
export function useSupported(callback: () => unknown, sync = false) {
|
||||||
const isSupported = ref() as Ref<boolean>;
|
const isSupported = shallowRef<boolean>();
|
||||||
|
|
||||||
const update = () => (isSupported.value = Boolean(callback()));
|
const update = () => (isSupported.value = Boolean(callback()));
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, shallowRef } from 'vue';
|
||||||
import type { ScreenMap } from '../../_util/responsiveObserve';
|
import type { ScreenMap } from '../../_util/responsiveObserve';
|
||||||
import ResponsiveObserve from '../../_util/responsiveObserve';
|
import useResponsiveObserve from '../../_util/responsiveObserve';
|
||||||
|
|
||||||
function useBreakpoint(): Ref<ScreenMap> {
|
function useBreakpoint(): Ref<ScreenMap> {
|
||||||
const screens = ref<ScreenMap>({});
|
const screens = shallowRef<ScreenMap>({});
|
||||||
let token = null;
|
let token = null;
|
||||||
|
const responsiveObserve = useResponsiveObserve();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
token = ResponsiveObserve.subscribe(supportScreens => {
|
token = responsiveObserve.value.subscribe(supportScreens => {
|
||||||
screens.value = supportScreens;
|
screens.value = supportScreens;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
ResponsiveObserve.unsubscribe(token);
|
responsiveObserve.value.unsubscribe(token);
|
||||||
});
|
});
|
||||||
|
|
||||||
return screens;
|
return screens;
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
import type { RequiredMark } from '../../form/Form';
|
|
||||||
import type { ComputedRef, UnwrapRef } from 'vue';
|
|
||||||
import { computed, inject } from 'vue';
|
|
||||||
import type { ConfigProviderProps, CSPConfig, Direction, SizeType } from '../../config-provider';
|
|
||||||
import { defaultConfigProvider } from '../../config-provider';
|
|
||||||
import type { VueNode } from '../type';
|
|
||||||
import type { ValidateMessages } from '../../form/interface';
|
|
||||||
|
|
||||||
export default (
|
|
||||||
name: string,
|
|
||||||
props: Record<any, any>,
|
|
||||||
): {
|
|
||||||
configProvider: UnwrapRef<ConfigProviderProps>;
|
|
||||||
prefixCls: ComputedRef<string>;
|
|
||||||
rootPrefixCls: ComputedRef<string>;
|
|
||||||
direction: ComputedRef<Direction>;
|
|
||||||
size: ComputedRef<SizeType>;
|
|
||||||
getTargetContainer: ComputedRef<() => HTMLElement>;
|
|
||||||
space: ComputedRef<{ size: SizeType | number }>;
|
|
||||||
pageHeader: ComputedRef<{ ghost: boolean }>;
|
|
||||||
form?: ComputedRef<{
|
|
||||||
requiredMark?: RequiredMark;
|
|
||||||
colon?: boolean;
|
|
||||||
validateMessages?: ValidateMessages;
|
|
||||||
}>;
|
|
||||||
autoInsertSpaceInButton: ComputedRef<boolean>;
|
|
||||||
renderEmpty?: ComputedRef<(componentName?: string) => VueNode>;
|
|
||||||
virtual: ComputedRef<boolean>;
|
|
||||||
dropdownMatchSelectWidth: ComputedRef<boolean | number>;
|
|
||||||
getPopupContainer: ComputedRef<ConfigProviderProps['getPopupContainer']>;
|
|
||||||
getPrefixCls: ConfigProviderProps['getPrefixCls'];
|
|
||||||
autocomplete: ComputedRef<string>;
|
|
||||||
csp: ComputedRef<CSPConfig>;
|
|
||||||
} => {
|
|
||||||
const configProvider = inject<UnwrapRef<ConfigProviderProps>>(
|
|
||||||
'configProvider',
|
|
||||||
defaultConfigProvider,
|
|
||||||
);
|
|
||||||
const prefixCls = computed(() => configProvider.getPrefixCls(name, props.prefixCls));
|
|
||||||
const direction = computed(() => props.direction ?? configProvider.direction);
|
|
||||||
const rootPrefixCls = computed(() => configProvider.getPrefixCls());
|
|
||||||
const autoInsertSpaceInButton = computed(() => configProvider.autoInsertSpaceInButton);
|
|
||||||
const renderEmpty = computed(() => configProvider.renderEmpty);
|
|
||||||
const space = computed(() => configProvider.space);
|
|
||||||
const pageHeader = computed(() => configProvider.pageHeader);
|
|
||||||
const form = computed(() => configProvider.form);
|
|
||||||
const getTargetContainer = computed(
|
|
||||||
() => props.getTargetContainer || configProvider.getTargetContainer,
|
|
||||||
);
|
|
||||||
const getPopupContainer = computed(
|
|
||||||
() => props.getPopupContainer || configProvider.getPopupContainer,
|
|
||||||
);
|
|
||||||
|
|
||||||
const dropdownMatchSelectWidth = computed<boolean | number>(
|
|
||||||
() => props.dropdownMatchSelectWidth ?? configProvider.dropdownMatchSelectWidth,
|
|
||||||
);
|
|
||||||
const virtual = computed(
|
|
||||||
() =>
|
|
||||||
(props.virtual === undefined ? configProvider.virtual !== false : props.virtual !== false) &&
|
|
||||||
dropdownMatchSelectWidth.value !== false,
|
|
||||||
);
|
|
||||||
const size = computed(() => props.size || configProvider.componentSize);
|
|
||||||
const autocomplete = computed(() => props.autocomplete || configProvider.input?.autocomplete);
|
|
||||||
const csp = computed(() => configProvider.csp);
|
|
||||||
return {
|
|
||||||
configProvider,
|
|
||||||
prefixCls,
|
|
||||||
direction,
|
|
||||||
size,
|
|
||||||
getTargetContainer,
|
|
||||||
getPopupContainer,
|
|
||||||
space,
|
|
||||||
pageHeader,
|
|
||||||
form,
|
|
||||||
autoInsertSpaceInButton,
|
|
||||||
renderEmpty,
|
|
||||||
virtual,
|
|
||||||
dropdownMatchSelectWidth,
|
|
||||||
rootPrefixCls,
|
|
||||||
getPrefixCls: configProvider.getPrefixCls,
|
|
||||||
autocomplete,
|
|
||||||
csp,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { onBeforeUnmount, ref } from 'vue';
|
import { onBeforeUnmount, shallowRef } from 'vue';
|
||||||
|
|
||||||
const useDestroyed = () => {
|
const useDestroyed = () => {
|
||||||
const destroyed = ref(false);
|
const destroyed = shallowRef(false);
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
destroyed.value = true;
|
destroyed.value = true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, shallowRef } from 'vue';
|
||||||
import { detectFlexGapSupported } from '../styleChecker';
|
import { detectFlexGapSupported } from '../styleChecker';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const flexible = ref(false);
|
const flexible = shallowRef(false);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
flexible.value = detectFlexGapSupported();
|
flexible.value = detectFlexGapSupported();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import canUseDom from '../../_util/canUseDom';
|
||||||
|
|
||||||
|
let uuid = 0;
|
||||||
|
|
||||||
|
/** Is client side and not jsdom */
|
||||||
|
export const isBrowserClient = process.env.NODE_ENV !== 'test' && canUseDom();
|
||||||
|
|
||||||
|
/** Get unique id for accessibility usage */
|
||||||
|
export function getUUID(): number | string {
|
||||||
|
let retId: string | number;
|
||||||
|
|
||||||
|
// Test never reach
|
||||||
|
/* istanbul ignore if */
|
||||||
|
if (isBrowserClient) {
|
||||||
|
retId = uuid;
|
||||||
|
uuid += 1;
|
||||||
|
} else {
|
||||||
|
retId = 'TEST_OR_SSR';
|
||||||
|
}
|
||||||
|
|
||||||
|
return retId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useId(id = ref('')) {
|
||||||
|
// Inner id for accessibility usage. Only work in client side
|
||||||
|
const innerId = `vc_unique_${getUUID()}`;
|
||||||
|
|
||||||
|
return id.value || innerId;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
import { onBeforeUnmount, ref } from 'vue';
|
import { onBeforeUnmount, shallowRef } from 'vue';
|
||||||
import raf from '../raf';
|
import raf from '../raf';
|
||||||
|
|
||||||
export type Updater<State> = (prev: State) => State;
|
export type Updater<State> = (prev: State) => State;
|
||||||
|
@ -9,11 +9,11 @@ export type Updater<State> = (prev: State) => State;
|
||||||
export function useLayoutState<State>(
|
export function useLayoutState<State>(
|
||||||
defaultState: State,
|
defaultState: State,
|
||||||
): [Ref<State>, (updater: Updater<State>) => void] {
|
): [Ref<State>, (updater: Updater<State>) => void] {
|
||||||
const stateRef = ref(defaultState);
|
const stateRef = shallowRef(defaultState);
|
||||||
let tempState = stateRef.value;
|
let tempState = stateRef.value;
|
||||||
|
|
||||||
let updateBatchRef = [];
|
let updateBatchRef = [];
|
||||||
const rafRef = ref();
|
const rafRef = shallowRef();
|
||||||
function setFrameState(updater: Updater<State>) {
|
function setFrameState(updater: Updater<State>) {
|
||||||
raf.cancel(rafRef.value);
|
raf.cancel(rafRef.value);
|
||||||
updateBatchRef.push(updater);
|
updateBatchRef.push(updater);
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
import { computed, watchEffect } from 'vue';
|
||||||
|
import { updateCSS, removeCSS } from '../../vc-util/Dom/dynamicCSS';
|
||||||
|
import getScrollBarSize from '../../_util/getScrollBarSize';
|
||||||
|
|
||||||
|
const UNIQUE_ID = `vc-util-locker-${Date.now()}`;
|
||||||
|
|
||||||
|
let uuid = 0;
|
||||||
|
|
||||||
|
/**../vc-util/Dom/dynam
|
||||||
|
* Test usage export. Do not use in your production
|
||||||
|
*/
|
||||||
|
export function isBodyOverflowing() {
|
||||||
|
return (
|
||||||
|
document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) &&
|
||||||
|
window.innerWidth > document.body.offsetWidth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useScrollLocker(lock?: Ref<boolean>) {
|
||||||
|
const mergedLock = computed(() => !!lock && !!lock.value);
|
||||||
|
uuid += 1;
|
||||||
|
const id = `${UNIQUE_ID}_${uuid}`;
|
||||||
|
|
||||||
|
watchEffect(
|
||||||
|
onClear => {
|
||||||
|
if (mergedLock.value) {
|
||||||
|
const scrollbarSize = getScrollBarSize();
|
||||||
|
const isOverflow = isBodyOverflowing();
|
||||||
|
|
||||||
|
updateCSS(
|
||||||
|
`
|
||||||
|
html body {
|
||||||
|
overflow-y: hidden;
|
||||||
|
${isOverflow ? `width: calc(100% - ${scrollbarSize}px);` : ''}
|
||||||
|
}`,
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
removeCSS(id);
|
||||||
|
}
|
||||||
|
onClear(() => {
|
||||||
|
removeCSS(id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
import type { ComputedRef, UnwrapRef } from 'vue';
|
|
||||||
import { computed, inject, provide } from 'vue';
|
|
||||||
import type { ConfigProviderProps, SizeType } from '../../config-provider';
|
|
||||||
import { defaultConfigProvider } from '../../config-provider';
|
|
||||||
|
|
||||||
const sizeProvider = Symbol('SizeProvider');
|
|
||||||
|
|
||||||
const useProvideSize = <T = SizeType>(props: Record<any, any>): ComputedRef<T> => {
|
|
||||||
const configProvider = inject<UnwrapRef<ConfigProviderProps>>(
|
|
||||||
'configProvider',
|
|
||||||
defaultConfigProvider,
|
|
||||||
);
|
|
||||||
const size = computed<T>(() => props.size || configProvider.componentSize);
|
|
||||||
provide(sizeProvider, size);
|
|
||||||
return size;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useInjectSize = <T = SizeType>(props?: Record<any, any>): ComputedRef<T> => {
|
|
||||||
const size: ComputedRef<T> = props
|
|
||||||
? computed(() => props.size)
|
|
||||||
: inject(
|
|
||||||
sizeProvider,
|
|
||||||
computed(() => 'default' as unknown as T),
|
|
||||||
);
|
|
||||||
return size;
|
|
||||||
};
|
|
||||||
|
|
||||||
export { useInjectSize, sizeProvider, useProvideSize };
|
|
||||||
|
|
||||||
export default useProvideSize;
|
|
|
@ -1,110 +0,0 @@
|
||||||
// MIT License from https://github.com/kaimallea/isMobile
|
|
||||||
|
|
||||||
const applePhone = /iPhone/i;
|
|
||||||
const appleIpod = /iPod/i;
|
|
||||||
const appleTablet = /iPad/i;
|
|
||||||
const androidPhone = /\bAndroid(?:.+)Mobile\b/i; // Match 'Android' AND 'Mobile'
|
|
||||||
const androidTablet = /Android/i;
|
|
||||||
const amazonPhone = /\bAndroid(?:.+)SD4930UR\b/i;
|
|
||||||
const amazonTablet = /\bAndroid(?:.+)(?:KF[A-Z]{2,4})\b/i;
|
|
||||||
const windowsPhone = /Windows Phone/i;
|
|
||||||
const windowsTablet = /\bWindows(?:.+)ARM\b/i; // Match 'Windows' AND 'ARM'
|
|
||||||
const otherBlackberry = /BlackBerry/i;
|
|
||||||
const otherBlackberry10 = /BB10/i;
|
|
||||||
const otherOpera = /Opera Mini/i;
|
|
||||||
const otherChrome = /\b(CriOS|Chrome)(?:.+)Mobile/i;
|
|
||||||
const otherFirefox = /Mobile(?:.+)Firefox\b/i; // Match 'Mobile' AND 'Firefox'
|
|
||||||
|
|
||||||
function match(regex, userAgent) {
|
|
||||||
return regex.test(userAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isMobile(userAgent) {
|
|
||||||
let ua = userAgent || (typeof navigator !== 'undefined' ? navigator.userAgent : '');
|
|
||||||
|
|
||||||
// Facebook mobile app's integrated browser adds a bunch of strings that
|
|
||||||
// match everything. Strip it out if it exists.
|
|
||||||
let tmp = ua.split('[FBAN');
|
|
||||||
if (typeof tmp[1] !== 'undefined') {
|
|
||||||
[ua] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Twitter mobile app's integrated browser on iPad adds a "Twitter for
|
|
||||||
// iPhone" string. Same probably happens on other tablet platforms.
|
|
||||||
// This will confuse detection so strip it out if it exists.
|
|
||||||
tmp = ua.split('Twitter');
|
|
||||||
if (typeof tmp[1] !== 'undefined') {
|
|
||||||
[ua] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
apple: {
|
|
||||||
phone: match(applePhone, ua) && !match(windowsPhone, ua),
|
|
||||||
ipod: match(appleIpod, ua),
|
|
||||||
tablet: !match(applePhone, ua) && match(appleTablet, ua) && !match(windowsPhone, ua),
|
|
||||||
device:
|
|
||||||
(match(applePhone, ua) || match(appleIpod, ua) || match(appleTablet, ua)) &&
|
|
||||||
!match(windowsPhone, ua),
|
|
||||||
},
|
|
||||||
amazon: {
|
|
||||||
phone: match(amazonPhone, ua),
|
|
||||||
tablet: !match(amazonPhone, ua) && match(amazonTablet, ua),
|
|
||||||
device: match(amazonPhone, ua) || match(amazonTablet, ua),
|
|
||||||
},
|
|
||||||
android: {
|
|
||||||
phone:
|
|
||||||
(!match(windowsPhone, ua) && match(amazonPhone, ua)) ||
|
|
||||||
(!match(windowsPhone, ua) && match(androidPhone, ua)),
|
|
||||||
tablet:
|
|
||||||
!match(windowsPhone, ua) &&
|
|
||||||
!match(amazonPhone, ua) &&
|
|
||||||
!match(androidPhone, ua) &&
|
|
||||||
(match(amazonTablet, ua) || match(androidTablet, ua)),
|
|
||||||
device:
|
|
||||||
(!match(windowsPhone, ua) &&
|
|
||||||
(match(amazonPhone, ua) ||
|
|
||||||
match(amazonTablet, ua) ||
|
|
||||||
match(androidPhone, ua) ||
|
|
||||||
match(androidTablet, ua))) ||
|
|
||||||
match(/\bokhttp\b/i, ua),
|
|
||||||
},
|
|
||||||
windows: {
|
|
||||||
phone: match(windowsPhone, ua),
|
|
||||||
tablet: match(windowsTablet, ua),
|
|
||||||
device: match(windowsPhone, ua) || match(windowsTablet, ua),
|
|
||||||
},
|
|
||||||
other: {
|
|
||||||
blackberry: match(otherBlackberry, ua),
|
|
||||||
blackberry10: match(otherBlackberry10, ua),
|
|
||||||
opera: match(otherOpera, ua),
|
|
||||||
firefox: match(otherFirefox, ua),
|
|
||||||
chrome: match(otherChrome, ua),
|
|
||||||
device:
|
|
||||||
match(otherBlackberry, ua) ||
|
|
||||||
match(otherBlackberry10, ua) ||
|
|
||||||
match(otherOpera, ua) ||
|
|
||||||
match(otherFirefox, ua) ||
|
|
||||||
match(otherChrome, ua),
|
|
||||||
},
|
|
||||||
|
|
||||||
// Additional
|
|
||||||
any: null,
|
|
||||||
phone: null,
|
|
||||||
tablet: null,
|
|
||||||
};
|
|
||||||
result.any =
|
|
||||||
result.apple.device || result.android.device || result.windows.device || result.other.device;
|
|
||||||
|
|
||||||
// excludes 'other' devices and ipods, targeting touchscreen phones
|
|
||||||
result.phone = result.apple.phone || result.android.phone || result.windows.phone;
|
|
||||||
result.tablet = result.apple.tablet || result.android.tablet || result.windows.tablet;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultResult = {
|
|
||||||
...isMobile(),
|
|
||||||
isMobile,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defaultResult;
|
|
|
@ -71,6 +71,7 @@ const getSlots = ele => {
|
||||||
return { ...slots, ...getScopedSlots(ele) };
|
return { ...slots, ...getScopedSlots(ele) };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const skipFlattenKey = Symbol('skipFlatten');
|
||||||
const flattenChildren = (children = [], filterEmpty = true) => {
|
const flattenChildren = (children = [], filterEmpty = true) => {
|
||||||
const temp = Array.isArray(children) ? children : [children];
|
const temp = Array.isArray(children) ? children : [children];
|
||||||
const res = [];
|
const res = [];
|
||||||
|
@ -78,7 +79,11 @@ const flattenChildren = (children = [], filterEmpty = true) => {
|
||||||
if (Array.isArray(child)) {
|
if (Array.isArray(child)) {
|
||||||
res.push(...flattenChildren(child, filterEmpty));
|
res.push(...flattenChildren(child, filterEmpty));
|
||||||
} else if (child && child.type === Fragment) {
|
} else if (child && child.type === Fragment) {
|
||||||
res.push(...flattenChildren(child.children, filterEmpty));
|
if (child.key === skipFlattenKey) {
|
||||||
|
res.push(child);
|
||||||
|
} else {
|
||||||
|
res.push(...flattenChildren(child.children, filterEmpty));
|
||||||
|
}
|
||||||
} else if (child && isVNode(child)) {
|
} else if (child && isVNode(child)) {
|
||||||
if (filterEmpty && !isEmptyElement(child)) {
|
if (filterEmpty && !isEmptyElement(child)) {
|
||||||
res.push(child);
|
res.push(child);
|
||||||
|
|
|
@ -1,75 +1,85 @@
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import type { GlobalToken } from '../theme/interface';
|
||||||
|
import { useToken } from '../theme/internal';
|
||||||
|
|
||||||
export type Breakpoint = 'xxxl' | 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
export type Breakpoint = 'xxxl' | 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||||
export type BreakpointMap = Record<Breakpoint, string>;
|
export type BreakpointMap = Record<Breakpoint, string>;
|
||||||
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
|
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
|
||||||
export type ScreenSizeMap = Partial<Record<Breakpoint, number>>;
|
export type ScreenSizeMap = Partial<Record<Breakpoint, number>>;
|
||||||
|
|
||||||
export const responsiveArray: Breakpoint[] = ['xxxl', 'xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
export const responsiveArray: Breakpoint[] = ['xxxl', 'xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
||||||
|
|
||||||
export const responsiveMap: BreakpointMap = {
|
|
||||||
xs: '(max-width: 575px)',
|
|
||||||
sm: '(min-width: 576px)',
|
|
||||||
md: '(min-width: 768px)',
|
|
||||||
lg: '(min-width: 992px)',
|
|
||||||
xl: '(min-width: 1200px)',
|
|
||||||
xxl: '(min-width: 1600px)',
|
|
||||||
xxxl: '(min-width: 2000px)',
|
|
||||||
};
|
|
||||||
|
|
||||||
type SubscribeFunc = (screens: ScreenMap) => void;
|
type SubscribeFunc = (screens: ScreenMap) => void;
|
||||||
const subscribers = new Map<Number, SubscribeFunc>();
|
|
||||||
let subUid = -1;
|
|
||||||
let screens = {};
|
|
||||||
|
|
||||||
const responsiveObserve = {
|
const getResponsiveMap = (token: GlobalToken): BreakpointMap => ({
|
||||||
matchHandlers: {} as {
|
xs: `(max-width: ${token.screenXSMax}px)`,
|
||||||
[prop: string]: {
|
sm: `(min-width: ${token.screenSM}px)`,
|
||||||
mql: MediaQueryList;
|
md: `(min-width: ${token.screenMD}px)`,
|
||||||
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
|
lg: `(min-width: ${token.screenLG}px)`,
|
||||||
};
|
xl: `(min-width: ${token.screenXL}px)`,
|
||||||
},
|
xxl: `(min-width: ${token.screenXXL}px)`,
|
||||||
dispatch(pointMap: ScreenMap) {
|
xxxl: `{min-width: ${token.screenXXXL}px}`,
|
||||||
screens = pointMap;
|
});
|
||||||
subscribers.forEach(func => func(screens));
|
|
||||||
return subscribers.size >= 1;
|
export default function useResponsiveObserver() {
|
||||||
},
|
const [, token] = useToken();
|
||||||
subscribe(func: SubscribeFunc): number {
|
|
||||||
if (!subscribers.size) this.register();
|
return computed(() => {
|
||||||
subUid += 1;
|
const responsiveMap: BreakpointMap = getResponsiveMap(token.value);
|
||||||
subscribers.set(subUid, func);
|
const subscribers = new Map<Number, SubscribeFunc>();
|
||||||
func(screens);
|
let subUid = -1;
|
||||||
return subUid;
|
let screens = {};
|
||||||
},
|
|
||||||
unsubscribe(token: number) {
|
return {
|
||||||
subscribers.delete(token);
|
matchHandlers: {} as {
|
||||||
if (!subscribers.size) this.unregister();
|
[prop: string]: {
|
||||||
},
|
mql: MediaQueryList;
|
||||||
unregister() {
|
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
|
||||||
Object.keys(responsiveMap).forEach((screen: string) => {
|
};
|
||||||
const matchMediaQuery = responsiveMap[screen];
|
},
|
||||||
const handler = this.matchHandlers[matchMediaQuery];
|
dispatch(pointMap: ScreenMap) {
|
||||||
handler?.mql.removeListener(handler?.listener);
|
screens = pointMap;
|
||||||
});
|
subscribers.forEach(func => func(screens));
|
||||||
subscribers.clear();
|
return subscribers.size >= 1;
|
||||||
},
|
},
|
||||||
register() {
|
subscribe(func: SubscribeFunc): number {
|
||||||
Object.keys(responsiveMap).forEach((screen: string) => {
|
if (!subscribers.size) this.register();
|
||||||
const matchMediaQuery = responsiveMap[screen];
|
subUid += 1;
|
||||||
const listener = ({ matches }: { matches: boolean }) => {
|
subscribers.set(subUid, func);
|
||||||
this.dispatch({
|
func(screens);
|
||||||
...screens,
|
return subUid;
|
||||||
[screen]: matches,
|
},
|
||||||
|
unsubscribe(paramToken: number) {
|
||||||
|
subscribers.delete(paramToken);
|
||||||
|
if (!subscribers.size) this.unregister();
|
||||||
|
},
|
||||||
|
unregister() {
|
||||||
|
Object.keys(responsiveMap).forEach((screen: string) => {
|
||||||
|
const matchMediaQuery = responsiveMap[screen];
|
||||||
|
const handler = this.matchHandlers[matchMediaQuery];
|
||||||
|
handler?.mql.removeListener(handler?.listener);
|
||||||
});
|
});
|
||||||
};
|
subscribers.clear();
|
||||||
const mql = window.matchMedia(matchMediaQuery);
|
},
|
||||||
mql.addListener(listener);
|
register() {
|
||||||
this.matchHandlers[matchMediaQuery] = {
|
Object.keys(responsiveMap).forEach((screen: string) => {
|
||||||
mql,
|
const matchMediaQuery = responsiveMap[screen];
|
||||||
listener,
|
const listener = ({ matches }: { matches: boolean }) => {
|
||||||
};
|
this.dispatch({
|
||||||
|
...screens,
|
||||||
|
[screen]: matches,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const mql = window.matchMedia(matchMediaQuery);
|
||||||
|
mql.addListener(listener);
|
||||||
|
this.matchHandlers[matchMediaQuery] = {
|
||||||
|
mql,
|
||||||
|
listener,
|
||||||
|
};
|
||||||
|
|
||||||
listener(mql);
|
listener(mql);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
responsiveMap,
|
||||||
|
};
|
||||||
export default responsiveObserve;
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import raf from './raf';
|
import raf from './raf';
|
||||||
import getScroll, { isWindow } from './getScroll';
|
|
||||||
import { easeInOutCubic } from './easings';
|
import { easeInOutCubic } from './easings';
|
||||||
|
import getScroll, { isWindow } from './getScroll';
|
||||||
|
|
||||||
interface ScrollToOptions {
|
interface ScrollToOptions {
|
||||||
/** Scroll container, default as window */
|
/** Scroll container, default as window */
|
||||||
|
@ -23,8 +23,8 @@ export default function scrollTo(y: number, options: ScrollToOptions = {}) {
|
||||||
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
|
const nextScrollTop = easeInOutCubic(time > duration ? duration : time, scrollTop, y, duration);
|
||||||
if (isWindow(container)) {
|
if (isWindow(container)) {
|
||||||
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
|
(container as Window).scrollTo(window.pageXOffset, nextScrollTop);
|
||||||
} else if (container instanceof HTMLDocument || container.constructor.name === 'HTMLDocument') {
|
} else if (container instanceof Document || container.constructor.name === 'HTMLDocument') {
|
||||||
(container as HTMLDocument).documentElement.scrollTop = nextScrollTop;
|
(container as Document).documentElement.scrollTop = nextScrollTop;
|
||||||
} else {
|
} else {
|
||||||
(container as HTMLElement).scrollTop = nextScrollTop;
|
(container as HTMLElement).scrollTop = nextScrollTop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue';
|
||||||
|
|
||||||
function shallowEqual(objA, objB, compare, compareContext) {
|
function shallowEqual(objA: any, objB: any, compare?: any, compareContext?: any) {
|
||||||
let ret = compare ? compare.call(compareContext, objA, objB) : void 0;
|
let ret = compare ? compare.call(compareContext, objA, objB) : void 0;
|
||||||
|
|
||||||
if (ret !== void 0) {
|
if (ret !== void 0) {
|
||||||
|
@ -45,6 +45,6 @@ function shallowEqual(objA, objB, compare, compareContext) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (value, other, customizer, thisArg) {
|
export default function (value: any, other: any) {
|
||||||
return shallowEqual(toRaw(value), toRaw(other), customizer, thisArg);
|
return shallowEqual(toRaw(value), toRaw(other));
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import type { ValidateStatus } from '../form/FormItem';
|
||||||
|
import classNames from './classNames';
|
||||||
|
|
||||||
|
const InputStatuses = ['warning', 'error', ''] as const;
|
||||||
|
|
||||||
|
export type InputStatus = (typeof InputStatuses)[number];
|
||||||
|
|
||||||
|
export function getStatusClassNames(
|
||||||
|
prefixCls: string,
|
||||||
|
status?: ValidateStatus,
|
||||||
|
hasFeedback?: boolean,
|
||||||
|
) {
|
||||||
|
return classNames({
|
||||||
|
[`${prefixCls}-status-success`]: status === 'success',
|
||||||
|
[`${prefixCls}-status-warning`]: status === 'warning',
|
||||||
|
[`${prefixCls}-status-error`]: status === 'error',
|
||||||
|
[`${prefixCls}-status-validating`]: status === 'validating',
|
||||||
|
[`${prefixCls}-has-feedback`]: hasFeedback,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMergedStatus = (contextStatus?: ValidateStatus, customStatus?: InputStatus) =>
|
||||||
|
customStatus || contextStatus;
|
|
@ -1,42 +0,0 @@
|
||||||
import getScrollBarSize from './getScrollBarSize';
|
|
||||||
import setStyle from './setStyle';
|
|
||||||
|
|
||||||
function isBodyOverflowing() {
|
|
||||||
return (
|
|
||||||
document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) &&
|
|
||||||
window.innerWidth > document.body.offsetWidth
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let cacheStyle = {};
|
|
||||||
|
|
||||||
export default (close?: boolean) => {
|
|
||||||
if (!isBodyOverflowing() && !close) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/19729
|
|
||||||
const scrollingEffectClassName = 'ant-scrolling-effect';
|
|
||||||
const scrollingEffectClassNameReg = new RegExp(`${scrollingEffectClassName}`, 'g');
|
|
||||||
const bodyClassName = document.body.className;
|
|
||||||
|
|
||||||
if (close) {
|
|
||||||
if (!scrollingEffectClassNameReg.test(bodyClassName)) return;
|
|
||||||
setStyle(cacheStyle);
|
|
||||||
cacheStyle = {};
|
|
||||||
document.body.className = bodyClassName.replace(scrollingEffectClassNameReg, '').trim();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scrollBarSize = getScrollBarSize();
|
|
||||||
if (scrollBarSize) {
|
|
||||||
cacheStyle = setStyle({
|
|
||||||
position: 'relative',
|
|
||||||
width: `calc(100% - ${scrollBarSize}px)`,
|
|
||||||
});
|
|
||||||
if (!scrollingEffectClassNameReg.test(bodyClassName)) {
|
|
||||||
const addClassName = `${bodyClassName} ${scrollingEffectClassName}`;
|
|
||||||
document.body.className = addClassName.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,47 +1,29 @@
|
||||||
import raf from './raf';
|
import raf from './raf';
|
||||||
|
|
||||||
export default function throttleByAnimationFrame(fn: (...args: any[]) => void) {
|
type throttledFn = (...args: any[]) => void;
|
||||||
let requestId: number;
|
|
||||||
|
|
||||||
const later = (args: any[]) => () => {
|
type throttledCancelFn = { cancel: () => void };
|
||||||
|
|
||||||
|
function throttleByAnimationFrame<T extends any[]>(fn: (...args: T) => void) {
|
||||||
|
let requestId: number | null;
|
||||||
|
|
||||||
|
const later = (args: T) => () => {
|
||||||
requestId = null;
|
requestId = null;
|
||||||
fn(...args);
|
fn(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
const throttled = (...args: any[]) => {
|
const throttled: throttledFn & throttledCancelFn = (...args: T) => {
|
||||||
if (requestId == null) {
|
if (requestId == null) {
|
||||||
requestId = raf(later(args));
|
requestId = raf(later(args));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(throttled as any).cancel = () => raf.cancel(requestId!);
|
throttled.cancel = () => {
|
||||||
|
raf.cancel(requestId!);
|
||||||
|
requestId = null;
|
||||||
|
};
|
||||||
|
|
||||||
return throttled;
|
return throttled;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function throttleByAnimationFrameDecorator() {
|
export default throttleByAnimationFrame;
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
return function (target: any, key: string, descriptor: any) {
|
|
||||||
const fn = descriptor.value;
|
|
||||||
let definingProperty = false;
|
|
||||||
return {
|
|
||||||
configurable: true,
|
|
||||||
get() {
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (definingProperty || this === target.prototype || this.hasOwnProperty(key)) {
|
|
||||||
return fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
const boundFn = throttleByAnimationFrame(fn.bind(this));
|
|
||||||
definingProperty = true;
|
|
||||||
Object.defineProperty(this, key, {
|
|
||||||
value: boundFn,
|
|
||||||
configurable: true,
|
|
||||||
writable: true,
|
|
||||||
});
|
|
||||||
definingProperty = false;
|
|
||||||
return boundFn;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue';
|
||||||
import { defineComponent, ref, onMounted } from 'vue';
|
import { defineComponent, shallowRef, onMounted } from 'vue';
|
||||||
/**
|
/**
|
||||||
* Wrap of sub component which need use as Button capacity (like Icon component).
|
* Wrap of sub component which need use as Button capacity (like Icon component).
|
||||||
* This helps accessibility reader to tread as a interactive button to operation.
|
* This helps accessibility reader to tread as a interactive button to operation.
|
||||||
|
@ -25,7 +25,7 @@ const TransButton = defineComponent({
|
||||||
autofocus: { type: Boolean, default: undefined },
|
autofocus: { type: Boolean, default: undefined },
|
||||||
},
|
},
|
||||||
setup(props, { slots, emit, attrs, expose }) {
|
setup(props, { slots, emit, attrs, expose }) {
|
||||||
const domRef = ref();
|
const domRef = shallowRef();
|
||||||
const onKeyDown = (event: KeyboardEvent) => {
|
const onKeyDown = (event: KeyboardEvent) => {
|
||||||
const { keyCode } = event;
|
const { keyCode } = event;
|
||||||
if (keyCode === KeyCode.ENTER) {
|
if (keyCode === KeyCode.ENTER) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
export const groupKeysMap = (keys: string[]) => {
|
||||||
|
const map = new Map<string, number>();
|
||||||
|
keys.forEach((key, index) => {
|
||||||
|
map.set(key, index);
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const groupDisabledKeysMap = <RecordType extends any[]>(dataSource: RecordType) => {
|
||||||
|
const map = new Map<string, number>();
|
||||||
|
dataSource.forEach(({ disabled, key }, index) => {
|
||||||
|
if (disabled) {
|
||||||
|
map.set(key, index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
};
|
|
@ -9,7 +9,7 @@ import { nextTick, Transition, TransitionGroup } from 'vue';
|
||||||
import { tuple } from './type';
|
import { tuple } from './type';
|
||||||
|
|
||||||
const SelectPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
|
const SelectPlacements = tuple('bottomLeft', 'bottomRight', 'topLeft', 'topRight');
|
||||||
export type SelectCommonPlacement = typeof SelectPlacements[number];
|
export type SelectCommonPlacement = (typeof SelectPlacements)[number];
|
||||||
|
|
||||||
const getTransitionDirection = (placement: SelectCommonPlacement | undefined) => {
|
const getTransitionDirection = (placement: SelectCommonPlacement | undefined) => {
|
||||||
if (placement !== undefined && (placement === 'topLeft' || placement === 'topRight')) {
|
if (placement !== undefined && (placement === 'topLeft' || placement === 'topRight')) {
|
||||||
|
@ -27,7 +27,7 @@ export const getTransitionProps = (transitionName: string, opt: TransitionProps
|
||||||
// appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
|
// appearFromClass: `${transitionName}-appear ${transitionName}-appear-prepare`,
|
||||||
// appearActiveClass: `antdv-base-transtion`,
|
// appearActiveClass: `antdv-base-transtion`,
|
||||||
// appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
|
// appearToClass: `${transitionName}-appear ${transitionName}-appear-active`,
|
||||||
enterFromClass: `${transitionName}-enter ${transitionName}-enter-prepare`,
|
enterFromClass: `${transitionName}-enter ${transitionName}-enter-prepare ${transitionName}-enter-start`,
|
||||||
enterActiveClass: `${transitionName}-enter ${transitionName}-enter-prepare`,
|
enterActiveClass: `${transitionName}-enter ${transitionName}-enter-prepare`,
|
||||||
enterToClass: `${transitionName}-enter ${transitionName}-enter-active`,
|
enterToClass: `${transitionName}-enter ${transitionName}-enter-active`,
|
||||||
leaveFromClass: ` ${transitionName}-leave`,
|
leaveFromClass: ` ${transitionName}-leave`,
|
||||||
|
|
|
@ -15,7 +15,7 @@ export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer
|
||||||
/**
|
/**
|
||||||
* https://github.com/Microsoft/TypeScript/issues/29729
|
* https://github.com/Microsoft/TypeScript/issues/29729
|
||||||
*/
|
*/
|
||||||
export type LiteralUnion<T extends U, U> = T | (U & {});
|
export type LiteralUnion<T extends string> = T | (string & {});
|
||||||
|
|
||||||
export type Data = Record<string, unknown>;
|
export type Data = Record<string, unknown>;
|
||||||
|
|
||||||
|
@ -44,4 +44,49 @@ export const withInstall = <T>(comp: T) => {
|
||||||
|
|
||||||
export type MaybeRef<T> = T | Ref<T>;
|
export type MaybeRef<T> = T | Ref<T>;
|
||||||
|
|
||||||
|
export function eventType<T>() {
|
||||||
|
return { type: [Function, Array] as PropType<T | T[]> };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function objectType<T = {}>(defaultVal?: T) {
|
||||||
|
return { type: Object as PropType<T>, default: defaultVal as T };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function booleanType(defaultVal?: boolean) {
|
||||||
|
return { type: Boolean, default: defaultVal as boolean };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function functionType<T = () => {}>(defaultVal?: T) {
|
||||||
|
return { type: Function as PropType<T>, default: defaultVal as T };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function anyType<T = any>(defaultVal?: T, required?: boolean) {
|
||||||
|
const type = { validator: () => true, default: defaultVal as T } as unknown;
|
||||||
|
return required
|
||||||
|
? (type as {
|
||||||
|
type: PropType<T>;
|
||||||
|
default: T;
|
||||||
|
required: true;
|
||||||
|
})
|
||||||
|
: (type as {
|
||||||
|
default: T;
|
||||||
|
type: PropType<T>;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function vNodeType<T = VueNode>() {
|
||||||
|
return { validator: () => true } as unknown as { type: PropType<T> };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function arrayType<T extends any[]>(defaultVal?: T) {
|
||||||
|
return { type: Array as unknown as PropType<T>, default: defaultVal as T };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stringType<T extends string = string>(defaultVal?: T) {
|
||||||
|
return { type: String as unknown as PropType<T>, default: defaultVal as T };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function someType<T>(types?: any[], defaultVal?: T) {
|
||||||
|
return types ? { type: types as PropType<T>, default: defaultVal as T } : anyType<T>(defaultVal);
|
||||||
|
}
|
||||||
|
|
||||||
export type CustomSlotsType<T> = SlotsType<T>;
|
export type CustomSlotsType<T> = SlotsType<T>;
|
||||||
|
|
|
@ -56,7 +56,7 @@ function resolvePropValue(options, props, key, value) {
|
||||||
|
|
||||||
export function getDataAndAriaProps(props) {
|
export function getDataAndAriaProps(props) {
|
||||||
return Object.keys(props).reduce((memo, key) => {
|
return Object.keys(props).reduce((memo, key) => {
|
||||||
if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-') {
|
if (key.startsWith('data-') || key.startsWith('aria-')) {
|
||||||
memo[key] = props[key];
|
memo[key] = props[key];
|
||||||
}
|
}
|
||||||
return memo;
|
return memo;
|
||||||
|
@ -78,5 +78,24 @@ export function renderHelper<T = Record<string, any>>(
|
||||||
}
|
}
|
||||||
return v ?? defaultV;
|
return v ?? defaultV;
|
||||||
}
|
}
|
||||||
|
export function wrapPromiseFn(openFn: (resolve: VoidFunction) => VoidFunction) {
|
||||||
|
let closeFn: VoidFunction;
|
||||||
|
|
||||||
|
const closePromise = new Promise<boolean>(resolve => {
|
||||||
|
closeFn = openFn(() => {
|
||||||
|
resolve(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const result: any = () => {
|
||||||
|
closeFn?.();
|
||||||
|
};
|
||||||
|
|
||||||
|
result.then = (filled: VoidFunction, rejected: VoidFunction) =>
|
||||||
|
closePromise.then(filled, rejected);
|
||||||
|
result.promise = closePromise;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export { isOn, cacheStringFunction, camelize, hyphenate, capitalize, resolvePropValue };
|
export { isOn, cacheStringFunction, camelize, hyphenate, capitalize, resolvePropValue };
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import warning, { resetWarned } from '../vc-util/warning';
|
|
||||||
|
|
||||||
export { resetWarned };
|
|
||||||
|
|
||||||
export default (valid, component, message = '') => {
|
|
||||||
warning(valid, `[antdv: ${component}] ${message}`);
|
|
||||||
};
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import vcWarning, { resetWarned } from '../vc-util/warning';
|
||||||
|
|
||||||
|
export { resetWarned };
|
||||||
|
export function noop() {}
|
||||||
|
|
||||||
|
type Warning = (valid: boolean, component: string, message?: string) => void;
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-mutable-exports
|
||||||
|
let warning: Warning = noop;
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
warning = (valid, component, message) => {
|
||||||
|
vcWarning(valid, `[ant-design-vue: ${component}] ${message}`);
|
||||||
|
|
||||||
|
// StrictMode will inject console which will not throw warning in React 17.
|
||||||
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
resetWarned();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default warning;
|
|
@ -1,178 +0,0 @@
|
||||||
import { nextTick, defineComponent, getCurrentInstance, onMounted, onBeforeUnmount } from 'vue';
|
|
||||||
import TransitionEvents from './css-animation/Event';
|
|
||||||
import raf from './raf';
|
|
||||||
import { findDOMNode } from './props-util';
|
|
||||||
import useConfigInject from './hooks/useConfigInject';
|
|
||||||
let styleForPesudo: HTMLStyleElement;
|
|
||||||
|
|
||||||
// Where el is the DOM element you'd like to test for visibility
|
|
||||||
function isHidden(element: HTMLElement) {
|
|
||||||
if (process.env.NODE_ENV === 'test') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !element || element.offsetParent === null;
|
|
||||||
}
|
|
||||||
function isNotGrey(color: string) {
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
|
||||||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/);
|
|
||||||
if (match && match[1] && match[2] && match[3]) {
|
|
||||||
return !(match[1] === match[2] && match[2] === match[3]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
export default defineComponent({
|
|
||||||
compatConfig: { MODE: 3 },
|
|
||||||
name: 'Wave',
|
|
||||||
props: {
|
|
||||||
insertExtraNode: Boolean,
|
|
||||||
disabled: Boolean,
|
|
||||||
},
|
|
||||||
setup(props, { slots, expose }) {
|
|
||||||
const instance = getCurrentInstance();
|
|
||||||
const { csp, prefixCls } = useConfigInject('', props);
|
|
||||||
expose({
|
|
||||||
csp,
|
|
||||||
});
|
|
||||||
let eventIns = null;
|
|
||||||
let clickWaveTimeoutId = null;
|
|
||||||
let animationStartId = null;
|
|
||||||
let animationStart = false;
|
|
||||||
let extraNode = null;
|
|
||||||
let isUnmounted = false;
|
|
||||||
const onTransitionStart = e => {
|
|
||||||
if (isUnmounted) return;
|
|
||||||
|
|
||||||
const node = findDOMNode(instance);
|
|
||||||
if (!e || e.target !== node) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!animationStart) {
|
|
||||||
resetEffect(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const onTransitionEnd = (e: any) => {
|
|
||||||
if (!e || e.animationName !== 'fadeEffect') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resetEffect(e.target);
|
|
||||||
};
|
|
||||||
const getAttributeName = () => {
|
|
||||||
const { insertExtraNode } = props;
|
|
||||||
return insertExtraNode
|
|
||||||
? `${prefixCls.value}-click-animating`
|
|
||||||
: `${prefixCls.value}-click-animating-without-extra-node`;
|
|
||||||
};
|
|
||||||
const onClick = (node: HTMLElement, waveColor: string) => {
|
|
||||||
const { insertExtraNode, disabled } = props;
|
|
||||||
if (disabled || !node || isHidden(node) || node.className.indexOf('-leave') >= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
extraNode = document.createElement('div');
|
|
||||||
extraNode.className = `${prefixCls.value}-click-animating-node`;
|
|
||||||
const attributeName = getAttributeName();
|
|
||||||
node.removeAttribute(attributeName);
|
|
||||||
node.setAttribute(attributeName, 'true');
|
|
||||||
// Not white or transparent or grey
|
|
||||||
styleForPesudo = styleForPesudo || document.createElement('style');
|
|
||||||
if (
|
|
||||||
waveColor &&
|
|
||||||
waveColor !== '#ffffff' &&
|
|
||||||
waveColor !== 'rgb(255, 255, 255)' &&
|
|
||||||
isNotGrey(waveColor) &&
|
|
||||||
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color
|
|
||||||
waveColor !== 'transparent'
|
|
||||||
) {
|
|
||||||
// Add nonce if CSP exist
|
|
||||||
if (csp.value?.nonce) {
|
|
||||||
styleForPesudo.nonce = csp.value.nonce;
|
|
||||||
}
|
|
||||||
extraNode.style.borderColor = waveColor;
|
|
||||||
styleForPesudo.innerHTML = `
|
|
||||||
[${prefixCls.value}-click-animating-without-extra-node='true']::after, .${prefixCls.value}-click-animating-node {
|
|
||||||
--antd-wave-shadow-color: ${waveColor};
|
|
||||||
}`;
|
|
||||||
if (!document.body.contains(styleForPesudo)) {
|
|
||||||
document.body.appendChild(styleForPesudo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (insertExtraNode) {
|
|
||||||
node.appendChild(extraNode);
|
|
||||||
}
|
|
||||||
TransitionEvents.addStartEventListener(node, onTransitionStart);
|
|
||||||
TransitionEvents.addEndEventListener(node, onTransitionEnd);
|
|
||||||
};
|
|
||||||
const resetEffect = (node: HTMLElement) => {
|
|
||||||
if (!node || node === extraNode || !(node instanceof Element)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { insertExtraNode } = props;
|
|
||||||
const attributeName = getAttributeName();
|
|
||||||
node.setAttribute(attributeName, 'false'); // edge has bug on `removeAttribute` #14466
|
|
||||||
if (styleForPesudo) {
|
|
||||||
styleForPesudo.innerHTML = '';
|
|
||||||
}
|
|
||||||
if (insertExtraNode && extraNode && node.contains(extraNode)) {
|
|
||||||
node.removeChild(extraNode);
|
|
||||||
}
|
|
||||||
TransitionEvents.removeStartEventListener(node, onTransitionStart);
|
|
||||||
TransitionEvents.removeEndEventListener(node, onTransitionEnd);
|
|
||||||
};
|
|
||||||
const bindAnimationEvent = (node: HTMLElement) => {
|
|
||||||
if (
|
|
||||||
!node ||
|
|
||||||
!node.getAttribute ||
|
|
||||||
node.getAttribute('disabled') ||
|
|
||||||
node.className.indexOf('disabled') >= 0
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newClick = (e: MouseEvent) => {
|
|
||||||
// Fix radio button click twice
|
|
||||||
if ((e.target as any).tagName === 'INPUT' || isHidden(e.target as HTMLElement)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resetEffect(node);
|
|
||||||
// Get wave color from target
|
|
||||||
const waveColor =
|
|
||||||
getComputedStyle(node).getPropertyValue('border-top-color') || // Firefox Compatible
|
|
||||||
getComputedStyle(node).getPropertyValue('border-color') ||
|
|
||||||
getComputedStyle(node).getPropertyValue('background-color');
|
|
||||||
clickWaveTimeoutId = setTimeout(() => onClick(node, waveColor), 0);
|
|
||||||
raf.cancel(animationStartId);
|
|
||||||
animationStart = true;
|
|
||||||
|
|
||||||
// Render to trigger transition event cost 3 frames. Let's delay 10 frames to reset this.
|
|
||||||
animationStartId = raf(() => {
|
|
||||||
animationStart = false;
|
|
||||||
}, 10);
|
|
||||||
};
|
|
||||||
node.addEventListener('click', newClick, true);
|
|
||||||
return {
|
|
||||||
cancel: () => {
|
|
||||||
node.removeEventListener('click', newClick, true);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
const node = findDOMNode(instance);
|
|
||||||
if (node.nodeType !== 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eventIns = bindAnimationEvent(node);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (eventIns) {
|
|
||||||
eventIns.cancel();
|
|
||||||
}
|
|
||||||
clearTimeout(clickWaveTimeoutId);
|
|
||||||
isUnmounted = true;
|
|
||||||
});
|
|
||||||
return () => {
|
|
||||||
return slots.default?.()[0];
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
import type { CSSProperties } from 'vue';
|
||||||
|
import { onBeforeUnmount, onMounted, Transition, render, defineComponent, shallowRef } from 'vue';
|
||||||
|
import useState from '../hooks/useState';
|
||||||
|
import { objectType } from '../type';
|
||||||
|
import { getTargetWaveColor } from './util';
|
||||||
|
import wrapperRaf from '../raf';
|
||||||
|
function validateNum(value: number) {
|
||||||
|
return Number.isNaN(value) ? 0 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WaveEffectProps {
|
||||||
|
className: string;
|
||||||
|
target: HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WaveEffect = defineComponent({
|
||||||
|
props: {
|
||||||
|
target: objectType<HTMLElement>(),
|
||||||
|
className: String,
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const divRef = shallowRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const [color, setWaveColor] = useState<string | null>(null);
|
||||||
|
const [borderRadius, setBorderRadius] = useState<number[]>([]);
|
||||||
|
const [left, setLeft] = useState(0);
|
||||||
|
const [top, setTop] = useState(0);
|
||||||
|
const [width, setWidth] = useState(0);
|
||||||
|
const [height, setHeight] = useState(0);
|
||||||
|
const [enabled, setEnabled] = useState(false);
|
||||||
|
|
||||||
|
function syncPos() {
|
||||||
|
const { target } = props;
|
||||||
|
const nodeStyle = getComputedStyle(target);
|
||||||
|
|
||||||
|
// Get wave color from target
|
||||||
|
setWaveColor(getTargetWaveColor(target));
|
||||||
|
|
||||||
|
const isStatic = nodeStyle.position === 'static';
|
||||||
|
|
||||||
|
// Rect
|
||||||
|
const { borderLeftWidth, borderTopWidth } = nodeStyle;
|
||||||
|
setLeft(isStatic ? target.offsetLeft : validateNum(-parseFloat(borderLeftWidth)));
|
||||||
|
setTop(isStatic ? target.offsetTop : validateNum(-parseFloat(borderTopWidth)));
|
||||||
|
setWidth(target.offsetWidth);
|
||||||
|
setHeight(target.offsetHeight);
|
||||||
|
|
||||||
|
// Get border radius
|
||||||
|
const {
|
||||||
|
borderTopLeftRadius,
|
||||||
|
borderTopRightRadius,
|
||||||
|
borderBottomLeftRadius,
|
||||||
|
borderBottomRightRadius,
|
||||||
|
} = nodeStyle;
|
||||||
|
|
||||||
|
setBorderRadius(
|
||||||
|
[
|
||||||
|
borderTopLeftRadius,
|
||||||
|
borderTopRightRadius,
|
||||||
|
borderBottomRightRadius,
|
||||||
|
borderBottomLeftRadius,
|
||||||
|
].map(radius => validateNum(parseFloat(radius))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Add resize observer to follow size
|
||||||
|
let resizeObserver: ResizeObserver;
|
||||||
|
let rafId: number;
|
||||||
|
let timeoutId: any;
|
||||||
|
const clear = () => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
wrapperRaf.cancel(rafId);
|
||||||
|
resizeObserver?.disconnect();
|
||||||
|
};
|
||||||
|
const removeDom = () => {
|
||||||
|
const holder = divRef.value?.parentElement;
|
||||||
|
if (holder) {
|
||||||
|
render(null, holder);
|
||||||
|
if (holder.parentElement) {
|
||||||
|
holder.parentElement.removeChild(holder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
clear();
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
removeDom();
|
||||||
|
}, 5000);
|
||||||
|
const { target } = props;
|
||||||
|
if (target) {
|
||||||
|
// We need delay to check position here
|
||||||
|
// since UI may change after click
|
||||||
|
rafId = wrapperRaf(() => {
|
||||||
|
syncPos();
|
||||||
|
|
||||||
|
setEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof ResizeObserver !== 'undefined') {
|
||||||
|
resizeObserver = new ResizeObserver(syncPos);
|
||||||
|
|
||||||
|
resizeObserver.observe(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
const onTransitionend = (e: TransitionEvent) => {
|
||||||
|
if (e.propertyName === 'opacity') {
|
||||||
|
removeDom();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return () => {
|
||||||
|
if (!enabled.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const waveStyle = {
|
||||||
|
left: `${left.value}px`,
|
||||||
|
top: `${top.value}px`,
|
||||||
|
width: `${width.value}px`,
|
||||||
|
height: `${height.value}px`,
|
||||||
|
borderRadius: borderRadius.value.map(radius => `${radius}px`).join(' '),
|
||||||
|
} as CSSProperties & {
|
||||||
|
[name: string]: number | string;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (color) {
|
||||||
|
waveStyle['--wave-color'] = color.value as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition
|
||||||
|
appear
|
||||||
|
name="wave-motion"
|
||||||
|
appearFromClass="wave-motion-appear"
|
||||||
|
appearActiveClass="wave-motion-appear"
|
||||||
|
appearToClass="wave-motion-appear wave-motion-appear-active"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref={divRef}
|
||||||
|
class={props.className}
|
||||||
|
style={waveStyle}
|
||||||
|
onTransitionend={onTransitionend}
|
||||||
|
/>
|
||||||
|
</Transition>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function showWaveEffect(node: HTMLElement, className: string) {
|
||||||
|
// Create holder
|
||||||
|
const holder = document.createElement('div');
|
||||||
|
holder.style.position = 'absolute';
|
||||||
|
holder.style.left = `0px`;
|
||||||
|
holder.style.top = `0px`;
|
||||||
|
node?.insertBefore(holder, node?.firstChild);
|
||||||
|
|
||||||
|
render(<WaveEffect target={node} className={className} />, holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default showWaveEffect;
|
|
@ -0,0 +1,96 @@
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
getCurrentInstance,
|
||||||
|
nextTick,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
|
import useConfigInject from '../../config-provider/hooks/useConfigInject';
|
||||||
|
import isVisible from '../../vc-util/Dom/isVisible';
|
||||||
|
import classNames from '../classNames';
|
||||||
|
import { findDOMNode } from '../props-util';
|
||||||
|
import useStyle from './style';
|
||||||
|
import useWave from './useWave';
|
||||||
|
|
||||||
|
export interface WaveProps {
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
compatConfig: { MODE: 3 },
|
||||||
|
name: 'Wave',
|
||||||
|
props: {
|
||||||
|
disabled: Boolean,
|
||||||
|
},
|
||||||
|
setup(props, { slots }) {
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
const { prefixCls } = useConfigInject('wave', props);
|
||||||
|
|
||||||
|
// ============================== Style ===============================
|
||||||
|
const [, hashId] = useStyle(prefixCls);
|
||||||
|
|
||||||
|
// =============================== Wave ===============================
|
||||||
|
const showWave = useWave(
|
||||||
|
instance,
|
||||||
|
computed(() => classNames(prefixCls.value, hashId.value)),
|
||||||
|
);
|
||||||
|
let onClick: (e: MouseEvent) => void;
|
||||||
|
const clear = () => {
|
||||||
|
const node = findDOMNode(instance);
|
||||||
|
node.removeEventListener('click', onClick, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
watch(
|
||||||
|
() => props.disabled,
|
||||||
|
() => {
|
||||||
|
clear();
|
||||||
|
nextTick(() => {
|
||||||
|
const node = findDOMNode(instance);
|
||||||
|
|
||||||
|
if (!node || node.nodeType !== 1 || props.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click handler
|
||||||
|
const onClick = (e: MouseEvent) => {
|
||||||
|
// Fix radio button click twice
|
||||||
|
if (
|
||||||
|
(e.target as HTMLElement).tagName === 'INPUT' ||
|
||||||
|
!isVisible(e.target as HTMLElement) ||
|
||||||
|
// No need wave
|
||||||
|
!node.getAttribute ||
|
||||||
|
node.getAttribute('disabled') ||
|
||||||
|
(node as HTMLInputElement).disabled ||
|
||||||
|
node.className.includes('disabled') ||
|
||||||
|
node.className.includes('-leave')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showWave();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind events
|
||||||
|
node.addEventListener('click', onClick, true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
flush: 'post',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// ============================== Render ==============================
|
||||||
|
const children = slots.default?.()[0];
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { genComponentStyleHook } from '../../theme/internal';
|
||||||
|
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface ComponentToken {}
|
||||||
|
|
||||||
|
export type WaveToken = FullToken<'Wave'>;
|
||||||
|
|
||||||
|
const genWaveStyle: GenerateStyle<WaveToken> = token => {
|
||||||
|
const { componentCls, colorPrimary } = token;
|
||||||
|
return {
|
||||||
|
[componentCls]: {
|
||||||
|
position: 'absolute',
|
||||||
|
background: 'transparent',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
color: `var(--wave-color, ${colorPrimary})`,
|
||||||
|
|
||||||
|
boxShadow: `0 0 0 0 currentcolor`,
|
||||||
|
opacity: 0.2,
|
||||||
|
|
||||||
|
// =================== Motion ===================
|
||||||
|
'&.wave-motion-appear': {
|
||||||
|
transition: [
|
||||||
|
`box-shadow 0.4s ${token.motionEaseOutCirc}`,
|
||||||
|
`opacity 2s ${token.motionEaseOutCirc}`,
|
||||||
|
].join(','),
|
||||||
|
|
||||||
|
'&-active': {
|
||||||
|
boxShadow: `0 0 0 6px currentcolor`,
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default genComponentStyleHook('Wave', token => [genWaveStyle(token)]);
|
|
@ -0,0 +1,16 @@
|
||||||
|
import type { ComponentInternalInstance, Ref } from 'vue';
|
||||||
|
import { findDOMNode } from '../props-util';
|
||||||
|
import showWaveEffect from './WaveEffect';
|
||||||
|
|
||||||
|
export default function useWave(
|
||||||
|
instance: ComponentInternalInstance | null,
|
||||||
|
className: Ref<string>,
|
||||||
|
): VoidFunction {
|
||||||
|
function showWave() {
|
||||||
|
const node = findDOMNode(instance);
|
||||||
|
|
||||||
|
showWaveEffect(node, className.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return showWave;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
export function isNotGrey(color: string) {
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\d.]*)?\)/);
|
||||||
|
if (match && match[1] && match[2] && match[3]) {
|
||||||
|
return !(match[1] === match[2] && match[2] === match[3]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isValidWaveColor(color: string) {
|
||||||
|
return (
|
||||||
|
color &&
|
||||||
|
color !== '#fff' &&
|
||||||
|
color !== '#ffffff' &&
|
||||||
|
color !== 'rgb(255, 255, 255)' &&
|
||||||
|
color !== 'rgba(255, 255, 255, 1)' &&
|
||||||
|
isNotGrey(color) &&
|
||||||
|
!/rgba\((?:\d*, ){3}0\)/.test(color) && // any transparent rgba color
|
||||||
|
color !== 'transparent'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTargetWaveColor(node: HTMLElement) {
|
||||||
|
const { borderTopColor, borderColor, backgroundColor } = getComputedStyle(node);
|
||||||
|
if (isValidWaveColor(borderTopColor)) {
|
||||||
|
return borderTopColor;
|
||||||
|
}
|
||||||
|
if (isValidWaveColor(borderColor)) {
|
||||||
|
return borderColor;
|
||||||
|
}
|
||||||
|
if (isValidWaveColor(backgroundColor)) {
|
||||||
|
return backgroundColor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
exports[`renders ./components/affix/demo/basic.vue correctly 1`] = `
|
exports[`renders ./components/affix/demo/basic.vue correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
|
<!---->
|
||||||
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
||||||
<!----><span>Affix top</span>
|
<!----><span>Affix top</span>
|
||||||
</button></div>
|
</button></div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<div>
|
<div>
|
||||||
|
<!---->
|
||||||
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
||||||
<!----><span>Affix bottom</span>
|
<!----><span>Affix bottom</span>
|
||||||
</button></div>
|
</button></div>
|
||||||
|
@ -16,7 +18,8 @@ exports[`renders ./components/affix/demo/basic.vue correctly 1`] = `
|
||||||
|
|
||||||
exports[`renders ./components/affix/demo/on-change.vue correctly 1`] = `
|
exports[`renders ./components/affix/demo/on-change.vue correctly 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div class=""><button class="ant-btn" type="button">
|
<!---->
|
||||||
|
<div class=""><button class="ant-btn ant-btn-default" type="button">
|
||||||
<!----><span>120px to affix top</span>
|
<!----><span>120px to affix top</span>
|
||||||
</button></div>
|
</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,6 +29,7 @@ exports[`renders ./components/affix/demo/target.vue correctly 1`] = `
|
||||||
<div id="components-affix-demo-target" class="scrollable-container">
|
<div id="components-affix-demo-target" class="scrollable-container">
|
||||||
<div class="background">
|
<div class="background">
|
||||||
<div>
|
<div>
|
||||||
|
<!---->
|
||||||
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
<div class=""><button class="ant-btn ant-btn-primary" type="button">
|
||||||
<!----><span>Fixed at the top of container</span>
|
<!----><span>Fixed at the top of container</span>
|
||||||
</button></div>
|
</button></div>
|
||||||
|
|
|
@ -26,16 +26,8 @@ The simplest usage.
|
||||||
</a-affix>
|
</a-affix>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
export default defineComponent({
|
const top = ref<number>(10);
|
||||||
setup() {
|
const bottom = ref<number>(10);
|
||||||
const top = ref<number>(10);
|
|
||||||
const bottom = ref<number>(10);
|
|
||||||
return {
|
|
||||||
top,
|
|
||||||
bottom,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -21,17 +21,8 @@ Callback with affixed state.
|
||||||
<a-button>120px to affix top</a-button>
|
<a-button>120px to affix top</a-button>
|
||||||
</a-affix>
|
</a-affix>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
const change = (affixed: boolean) => {
|
||||||
export default defineComponent({
|
console.log(affixed);
|
||||||
setup() {
|
};
|
||||||
const change = (affixed: boolean) => {
|
|
||||||
console.log(affixed);
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
change,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,23 +25,16 @@ Set a `target` for 'Affix', which is listen to scroll event of target element (d
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
const containerRef = ref();
|
||||||
export default defineComponent({
|
|
||||||
setup() {
|
|
||||||
const containerRef = ref();
|
|
||||||
return {
|
|
||||||
containerRef,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style scoped>
|
||||||
#components-affix-demo-target.scrollable-container {
|
#components-affix-demo-target.scrollable-container {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
#components-affix-demo-target .background {
|
#components-affix-demo-target .background {
|
||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
---
|
---
|
||||||
category: Components
|
category: Components
|
||||||
type: Navigation
|
type: Other
|
||||||
title: Affix
|
title: Affix
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*YSm4RI3iOJ8AAAAAAAAAAAAADrJ8AQ/original
|
||||||
|
coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*03dxS64LxeQAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
Wrap Affix around another component to make it stick the viewport.
|
Wrap Affix around another component to make it stick the viewport.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ComponentPublicInstance, CSSProperties, ExtractPropTypes, PropType } from 'vue';
|
import type { ComponentPublicInstance, CSSProperties, ExtractPropTypes, PropType } from 'vue';
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
ref,
|
shallowRef,
|
||||||
reactive,
|
reactive,
|
||||||
watch,
|
watch,
|
||||||
onMounted,
|
onMounted,
|
||||||
|
@ -21,9 +21,9 @@ import {
|
||||||
getFixedTop,
|
getFixedTop,
|
||||||
getFixedBottom,
|
getFixedBottom,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import omit from '../_util/omit';
|
import omit from '../_util/omit';
|
||||||
|
import useStyle from './style';
|
||||||
function getDefaultTarget() {
|
function getDefaultTarget() {
|
||||||
return typeof window !== 'undefined' ? window : null;
|
return typeof window !== 'undefined' ? window : null;
|
||||||
}
|
}
|
||||||
|
@ -74,10 +74,11 @@ export type AffixInstance = ComponentPublicInstance<AffixProps, AffixExpose>;
|
||||||
const Affix = defineComponent({
|
const Affix = defineComponent({
|
||||||
compatConfig: { MODE: 3 },
|
compatConfig: { MODE: 3 },
|
||||||
name: 'AAffix',
|
name: 'AAffix',
|
||||||
|
inheritAttrs: false,
|
||||||
props: affixProps(),
|
props: affixProps(),
|
||||||
setup(props, { slots, emit, expose }) {
|
setup(props, { slots, emit, expose, attrs }) {
|
||||||
const placeholderNode = ref();
|
const placeholderNode = shallowRef();
|
||||||
const fixedNode = ref();
|
const fixedNode = shallowRef();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
affixStyle: undefined,
|
affixStyle: undefined,
|
||||||
placeholderStyle: undefined,
|
placeholderStyle: undefined,
|
||||||
|
@ -123,6 +124,14 @@ const Affix = defineComponent({
|
||||||
const targetRect = getTargetRect(targetNode);
|
const targetRect = getTargetRect(targetNode);
|
||||||
const fixedTop = getFixedTop(placeholderRect, targetRect, offsetTop.value);
|
const fixedTop = getFixedTop(placeholderRect, targetRect, offsetTop.value);
|
||||||
const fixedBottom = getFixedBottom(placeholderRect, targetRect, offsetBottom.value);
|
const fixedBottom = getFixedBottom(placeholderRect, targetRect, offsetBottom.value);
|
||||||
|
if (
|
||||||
|
placeholderRect.top === 0 &&
|
||||||
|
placeholderRect.left === 0 &&
|
||||||
|
placeholderRect.width === 0 &&
|
||||||
|
placeholderRect.height === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fixedTop !== undefined) {
|
if (fixedTop !== undefined) {
|
||||||
const width = `${placeholderRect.width}px`;
|
const width = `${placeholderRect.width}px`;
|
||||||
|
@ -245,11 +254,12 @@ const Affix = defineComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
const { prefixCls } = useConfigInject('affix', props);
|
const { prefixCls } = useConfigInject('affix', props);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
return () => {
|
return () => {
|
||||||
const { affixStyle, placeholderStyle } = state;
|
const { affixStyle, placeholderStyle } = state;
|
||||||
const className = classNames({
|
const className = classNames({
|
||||||
[prefixCls.value]: affixStyle,
|
[prefixCls.value]: affixStyle,
|
||||||
|
[hashId.value]: true,
|
||||||
});
|
});
|
||||||
const restProps = omit(props, [
|
const restProps = omit(props, [
|
||||||
'prefixCls',
|
'prefixCls',
|
||||||
|
@ -259,14 +269,15 @@ const Affix = defineComponent({
|
||||||
'onChange',
|
'onChange',
|
||||||
'onTestUpdatePosition',
|
'onTestUpdatePosition',
|
||||||
]);
|
]);
|
||||||
return (
|
return wrapSSR(
|
||||||
<ResizeObserver onResize={updatePosition}>
|
<ResizeObserver onResize={updatePosition}>
|
||||||
<div {...restProps} style={placeholderStyle} ref={placeholderNode}>
|
<div {...restProps} {...attrs} ref={placeholderNode}>
|
||||||
|
{affixStyle && <div style={placeholderStyle} aria-hidden="true" />}
|
||||||
<div class={className} ref={fixedNode} style={affixStyle}>
|
<div class={className} ref={fixedNode} style={affixStyle}>
|
||||||
{slots.default?.()}
|
{slots.default?.()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ResizeObserver>
|
</ResizeObserver>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
category: Components
|
category: Components
|
||||||
subtitle: 固钉
|
subtitle: 固钉
|
||||||
type: 导航
|
type: 其他
|
||||||
title: Affix
|
title: Affix
|
||||||
cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*YSm4RI3iOJ8AAAAAAAAAAAAADrJ8AQ/original
|
||||||
|
coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*03dxS64LxeQAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
将页面元素钉在可视范围。
|
将页面元素钉在可视范围。
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
|
|
||||||
.@{ant-prefix}-affix {
|
|
||||||
position: fixed;
|
|
||||||
z-index: @zindex-affix;
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import type { CSSObject } from '../../_util/cssinjs';
|
||||||
|
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||||
|
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||||
|
|
||||||
|
interface AffixToken extends FullToken<'Affix'> {
|
||||||
|
zIndexPopup: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================== Shared ==============================
|
||||||
|
const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => {
|
||||||
|
const { componentCls } = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[componentCls]: {
|
||||||
|
position: 'fixed',
|
||||||
|
zIndex: token.zIndexPopup,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genComponentStyleHook('Affix', token => {
|
||||||
|
const affixToken = mergeToken<AffixToken>(token, {
|
||||||
|
zIndexPopup: token.zIndexBase + 10,
|
||||||
|
});
|
||||||
|
return [genSharedAffixStyle(affixToken)];
|
||||||
|
});
|
|
@ -1,2 +0,0 @@
|
||||||
import '../../style/index.less';
|
|
||||||
import './index.less';
|
|
|
@ -1,5 +1,4 @@
|
||||||
import addEventListener from '../vc-util/Dom/addEventListener';
|
import addEventListener from '../vc-util/Dom/addEventListener';
|
||||||
import type { ComponentPublicInstance } from 'vue';
|
|
||||||
import supportsPassive from '../_util/supportsPassive';
|
import supportsPassive from '../_util/supportsPassive';
|
||||||
|
|
||||||
export type BindElement = HTMLElement | Window | null | undefined;
|
export type BindElement = HTMLElement | Window | null | undefined;
|
||||||
|
@ -42,7 +41,7 @@ const TRIGGER_EVENTS = [
|
||||||
|
|
||||||
interface ObserverEntity {
|
interface ObserverEntity {
|
||||||
target: HTMLElement | Window;
|
target: HTMLElement | Window;
|
||||||
affixList: ComponentPublicInstance<any>[];
|
affixList: any[];
|
||||||
eventHandlers: { [eventName: string]: any };
|
eventHandlers: { [eventName: string]: any };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +52,10 @@ export function getObserverEntities() {
|
||||||
return observerEntities;
|
return observerEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addObserveTarget(
|
export function addObserveTarget<T>(target: HTMLElement | Window | null, affix: T): void {
|
||||||
target: HTMLElement | Window | null,
|
|
||||||
affix: ComponentPublicInstance<any>,
|
|
||||||
): void {
|
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
let entity: ObserverEntity | undefined = observerEntities.find(item => item.target === target);
|
let entity = observerEntities.find(item => item.target === target);
|
||||||
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
entity.affixList.push(affix);
|
entity.affixList.push(affix);
|
||||||
|
@ -88,7 +84,7 @@ export function addObserveTarget(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeObserveTarget(affix: ComponentPublicInstance<any>): void {
|
export function removeObserveTarget<T>(affix: T): void {
|
||||||
const observerEntity = observerEntities.find(oriObserverEntity => {
|
const observerEntity = observerEntities.find(oriObserverEntity => {
|
||||||
const hasAffix = oriObserverEntity.affixList.some(item => item === affix);
|
const hasAffix = oriObserverEntity.affixList.some(item => item === affix);
|
||||||
if (hasAffix) {
|
if (hasAffix) {
|
||||||
|
|
|
@ -1,34 +1,119 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`renders ./components/alert/demo/action.vue correctly 1`] = `
|
||||||
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-closable" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></span>
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Success Tips</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<div class="ant-alert-action"><button class="ant-btn ant-btn-text ant-btn-sm" type="button">
|
||||||
|
<!----><span>UNDO</span>
|
||||||
|
</button></div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Error Text</div>
|
||||||
|
<div class="ant-alert-description">Error Description Error Description Error Description Error Description</div>
|
||||||
|
</div>
|
||||||
|
<div class="ant-alert-action"><button class="ant-btn ant-btn-default ant-btn-sm ant-btn-dangerous" type="button">
|
||||||
|
<!----><span>Detail</span>
|
||||||
|
</button></div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable" data-show="true">
|
||||||
|
<!---->
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Warning Text</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<div class="ant-alert-action">
|
||||||
|
<div class="ant-space ant-space-horizontal ant-space-align-center">
|
||||||
|
<div class="ant-space-item"><button class="ant-btn ant-btn-ghost ant-btn-sm" type="button">
|
||||||
|
<!----><span>Done</span>
|
||||||
|
</button></div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<div class="ant-space-item">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon ant-alert-closable" data-show="true">
|
||||||
|
<!---->
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Info Text</div>
|
||||||
|
<div class="ant-alert-description">Info Description Info Description Info Description Info Description</div>
|
||||||
|
</div>
|
||||||
|
<div class="ant-alert-action">
|
||||||
|
<div class="ant-space ant-space-vertical">
|
||||||
|
<div class="ant-space-item" style="margin-bottom: 8px;"><button class="ant-btn ant-btn-primary ant-btn-sm" type="button">
|
||||||
|
<!----><span>Accept</span>
|
||||||
|
</button></div>
|
||||||
|
<!---->
|
||||||
|
<div class="ant-space-item"><button class="ant-btn ant-btn-ghost ant-btn-sm ant-btn-dangerous" type="button">
|
||||||
|
<!----><span>Decline</span>
|
||||||
|
</button></div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/banner.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/banner.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-banner" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
<div class="ant-alert-content">
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div class="ant-alert-message">Warning text</div>
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-banner" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
||||||
<!---->
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Warning text</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<br>
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-banner ant-alert-closable" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-banner ant-alert-closable" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-message">Very long warning text warning text text text text text text text</div>
|
||||||
<div class="ant-alert-message">Very long warning text warning text text text text text text text</div>
|
<!---->
|
||||||
<!---->
|
</div>
|
||||||
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
<!----><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-banner" data-show="true">
|
|
||||||
<!---->
|
|
||||||
<div class="ant-alert-content">
|
|
||||||
<div class="ant-alert-message">Warning text without icon</div>
|
|
||||||
<!---->
|
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<br>
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-banner" data-show="true">
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-banner" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error text</div>
|
<div class="ant-alert-message">Warning text without icon</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<div class="ant-space-item">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-banner" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Error text</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
|
@ -42,23 +127,34 @@ exports[`renders ./components/alert/demo/basic.vue correctly 1`] = `
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/closable.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/closable.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable" data-show="true">
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon ant-alert-closable" data-show="true">
|
||||||
|
<!---->
|
||||||
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!----><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-space-item">
|
||||||
<div class="ant-alert-message">Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text</div>
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon ant-alert-closable" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
<div class="ant-alert-content">
|
||||||
</div>
|
<div class="ant-alert-message">Error Text</div>
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon ant-alert-closable" data-show="true">
|
<div class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</div>
|
||||||
|
</div>
|
||||||
|
<!----><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
|
||||||
<div class="ant-alert-message">Error Text</div>
|
|
||||||
<div class="ant-alert-description">Error Description Error Description Error Description Error Description Error Description Error Description</div>
|
|
||||||
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -68,168 +164,259 @@ exports[`renders ./components/alert/demo/close-text.vue correctly 1`] = `
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Info Text</div>
|
<div class="ant-alert-message">Info Text</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span class="ant-alert-close-text">Close Now</span></button>
|
</div>
|
||||||
|
<!----><button type="button" class="ant-alert-close-icon" tabindex="0"><span class="ant-alert-close-text">Close Now</span></button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/custom-icon.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/custom-icon.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
<!---->
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div class="ant-alert-content">
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
|
||||||
<div class="ant-alert-message">showIcon = false</div>
|
<!---->
|
||||||
<!---->
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">showIcon = false</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Success Tips</div>
|
<div class="ant-alert-message">Success Tips</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Informational Notes</div>
|
<div class="ant-alert-message">Informational Notes</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning</div>
|
<div class="ant-alert-message">Warning</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error</div>
|
<div class="ant-alert-message">Error</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Success Tips</div>
|
<div class="ant-alert-message">Success Tips</div>
|
||||||
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
|
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Informational Notes</div>
|
<div class="ant-alert-message">Informational Notes</div>
|
||||||
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
|
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning</div>
|
<div class="ant-alert-message">Warning</div>
|
||||||
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
|
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item">
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="smile" class="anticon anticon-smile ant-alert-icon"><svg focusable="false" class="" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M288 421a48 48 0 1096 0 48 48 0 10-96 0zm352 0a48 48 0 1096 0 48 48 0 10-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 01248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 01249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 01775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 01775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 00-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 00-8-8.4z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error</div>
|
<div class="ant-alert-message">Error</div>
|
||||||
<div class="ant-alert-description">This is an error message about copywriting.</div>
|
<div class="ant-alert-description">This is an error message about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/description.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/description.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon" data-show="true">
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
<!---->
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div class="ant-alert-content">
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description ant-alert-no-icon" data-show="true">
|
||||||
<div class="ant-alert-message">Success Text</div>
|
<!---->
|
||||||
<div class="ant-alert-description">
|
<div class="ant-alert-content">
|
||||||
<p> Success Description <span style="color: red;">Success</span> Description Success Description </p>
|
<div class="ant-alert-message">Success Text</div>
|
||||||
|
<div class="ant-alert-description">
|
||||||
|
<p> Success Description <span style="color: red;">Success</span> Description Success Description </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Info Text</div>
|
<div class="ant-alert-message">Info Text</div>
|
||||||
<div class="ant-alert-description">Info Description Info Description Info Description Info Description</div>
|
<div class="ant-alert-description">Info Description Info Description Info Description Info Description</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning Text</div>
|
<div class="ant-alert-message">Warning Text</div>
|
||||||
<div class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</div>
|
<div class="ant-alert-description">Warning Description Warning Description Warning Description Warning Description</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item">
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error Text</div>
|
<div class="ant-alert-message">Error Text</div>
|
||||||
<div class="ant-alert-description">Error Description Error Description Error Description Error Description</div>
|
<div class="ant-alert-description">Error Description Error Description Error Description Error Description</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/icon.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/icon.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></span>
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
<div class="ant-alert-content">
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div class="ant-alert-message">Success Tips</div>
|
<div role="alert" class="ant-alert ant-alert-success" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm193.5 301.7l-210.6 292a31.8 31.8 0 01-51.7 0L318.5 484.9c-3.8-5.3 0-12.7 6.5-12.7h46.9c10.2 0 19.9 4.9 25.9 13.3l71.2 98.8 157.2-218c6-8.3 15.6-13.3 25.9-13.3H699c6.5 0 10.3 7.4 6.5 12.7z"></path></svg></span>
|
||||||
<!---->
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Success Tips</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-info" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm32 664c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V456c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272zm-32-344a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Informational Notes</div>
|
<div class="ant-alert-message">Informational Notes</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-warning" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning</div>
|
<div class="ant-alert-message">Warning</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-error" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 01-1.9-5.2c0-4.4 3.6-8 8-8l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error</div>
|
<div class="ant-alert-message">Error</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-with-description" data-show="true"><span role="img" aria-label="check-circle" class="anticon anticon-check-circle ant-alert-icon"><svg focusable="false" class="" data-icon="check-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"></path><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Success Tips</div>
|
<div class="ant-alert-message">Success Tips</div>
|
||||||
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
|
<div class="ant-alert-description">Detailed description and advices about successful copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-info ant-alert-with-description" data-show="true"><span role="img" aria-label="info-circle" class="anticon anticon-info-circle ant-alert-icon"><svg focusable="false" class="" data-icon="info-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Informational Notes</div>
|
<div class="ant-alert-message">Informational Notes</div>
|
||||||
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
|
<div class="ant-alert-description">Additional description and informations about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-with-description" data-show="true"><span role="img" aria-label="exclamation-circle" class="anticon anticon-exclamation-circle ant-alert-icon"><svg focusable="false" class="" data-icon="exclamation-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path><path d="M464 688a48 48 0 1096 0 48 48 0 10-96 0zm24-112h48c4.4 0 8-3.6 8-8V296c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning</div>
|
<div class="ant-alert-message">Warning</div>
|
||||||
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
|
<div class="ant-alert-description">This is a warning notice about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item">
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-with-description" data-show="true"><span role="img" aria-label="close-circle" class="anticon anticon-close-circle ant-alert-icon"><svg focusable="false" class="" data-icon="close-circle" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 00-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z"></path><path d="M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"></path></svg></span>
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error</div>
|
<div class="ant-alert-message">Error</div>
|
||||||
<div class="ant-alert-description">This is an error message about copywriting.</div>
|
<div class="ant-alert-description">This is an error message about copywriting.</div>
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
|
@ -241,40 +428,59 @@ exports[`renders ./components/alert/demo/smooth-closed.vue correctly 1`] = `
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Alert Message Text</div>
|
<div class="ant-alert-message">Alert Message Text</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
</div>
|
||||||
|
<!----><button type="button" class="ant-alert-close-icon" tabindex="0"><span role="img" aria-label="close" class="anticon anticon-close"><svg focusable="false" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></span></button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/alert/demo/style.vue correctly 1`] = `
|
exports[`renders ./components/alert/demo/style.vue correctly 1`] = `
|
||||||
<div role="alert" class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
|
<div style="width: 100%;" class="ant-space ant-space-vertical">
|
||||||
<!---->
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div class="ant-alert-content">
|
<div role="alert" class="ant-alert ant-alert-success ant-alert-no-icon" data-show="true">
|
||||||
<div class="ant-alert-message">Success Text</div>
|
<!---->
|
||||||
<!---->
|
<div class="ant-alert-content">
|
||||||
|
<div class="ant-alert-message">Success Text</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-info ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-info ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Info Text</div>
|
<div class="ant-alert-message">Info Text</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item" style="margin-bottom: 8px;">
|
||||||
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-warning ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Warning Text</div>
|
<div class="ant-alert-message">Warning Text</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
<div class="ant-space-item">
|
||||||
<div role="alert" class="ant-alert ant-alert-error ant-alert-no-icon" data-show="true">
|
<div role="alert" class="ant-alert ant-alert-error ant-alert-no-icon" data-show="true">
|
||||||
<!---->
|
<!---->
|
||||||
<div class="ant-alert-content">
|
<div class="ant-alert-content">
|
||||||
<div class="ant-alert-message">Error Text</div>
|
<div class="ant-alert-message">Error Text</div>
|
||||||
<!---->
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<docs>
|
||||||
|
---
|
||||||
|
order: 0
|
||||||
|
title:
|
||||||
|
zh-CN: 操作
|
||||||
|
en-US: Action
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
可以在右上角自定义操作项。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Custom action.
|
||||||
|
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-space direction="vertical" style="width: 100%">
|
||||||
|
<a-alert message="Success Tips" type="success" show-icon closable>
|
||||||
|
<template #action>
|
||||||
|
<a-button size="small" type="text">UNDO</a-button>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
message="Error Text"
|
||||||
|
show-icon
|
||||||
|
description="Error Description Error Description Error Description Error Description"
|
||||||
|
type="error"
|
||||||
|
>
|
||||||
|
<template #action>
|
||||||
|
<a-button size="small" danger>Detail</a-button>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert message="Warning Text" type="warning" closable>
|
||||||
|
<template #action>
|
||||||
|
<a-space>
|
||||||
|
<a-button size="small" type="ghost">Done</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
<a-alert
|
||||||
|
message="Info Text"
|
||||||
|
description="Info Description Info Description Info Description Info Description"
|
||||||
|
type="info"
|
||||||
|
closable
|
||||||
|
>
|
||||||
|
<template #action>
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<a-button size="small" type="primary">Accept</a-button>
|
||||||
|
<a-button size="small" danger type="ghost">Decline</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
|
@ -17,15 +17,14 @@ Display Alert as a banner at top of page.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-alert message="Warning text" banner />
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<br />
|
<a-alert message="Warning text" banner />
|
||||||
<a-alert
|
<a-alert
|
||||||
message="Very long warning text warning text text text text text text text"
|
message="Very long warning text warning text text text text text text text"
|
||||||
banner
|
banner
|
||||||
closable
|
closable
|
||||||
/>
|
/>
|
||||||
<br />
|
<a-alert :show-icon="false" message="Warning text without icon" banner />
|
||||||
<a-alert :show-icon="false" message="Warning text without icon" banner />
|
<a-alert type="error" message="Error text" banner />
|
||||||
<br />
|
</a-space>
|
||||||
<a-alert type="error" message="Error text" banner />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -17,31 +17,25 @@ To show close button.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-alert
|
<a-space direction="vertical" style="width: 100%">
|
||||||
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
<a-alert
|
||||||
type="warning"
|
message="Warning Text Warning Text Warning TextW arning Text Warning Text Warning TextWarning Text"
|
||||||
closable
|
type="warning"
|
||||||
@close="onClose"
|
closable
|
||||||
/>
|
@close="onClose"
|
||||||
<a-alert
|
/>
|
||||||
message="Error Text"
|
<a-alert
|
||||||
description="Error Description Error Description Error Description Error Description Error Description Error Description"
|
message="Error Text"
|
||||||
type="error"
|
description="Error Description Error Description Error Description Error Description Error Description Error Description"
|
||||||
closable
|
type="error"
|
||||||
@close="onClose"
|
closable
|
||||||
/>
|
@close="onClose"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
const onClose = (e: MouseEvent) => {
|
||||||
export default defineComponent({
|
console.log(e, 'I was closed.');
|
||||||
setup() {
|
};
|
||||||
const onClose = (e: MouseEvent) => {
|
|
||||||
console.log(e, 'I was closed.');
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
onClose,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,61 +17,57 @@ Custom Icon make information more clear and more friendly.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-alert message="showIcon = false" type="success">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<template #icon><smile-outlined /></template>
|
<a-alert message="showIcon = false" type="success">
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert message="Success Tips" type="success" show-icon>
|
</a-alert>
|
||||||
<template #icon><smile-outlined /></template>
|
<a-alert message="Success Tips" type="success" show-icon>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert message="Informational Notes" type="info" show-icon>
|
</a-alert>
|
||||||
<template #icon><smile-outlined /></template>
|
<a-alert message="Informational Notes" type="info" show-icon>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert message="Warning" type="warning" show-icon>
|
</a-alert>
|
||||||
<template #icon><smile-outlined /></template>
|
<a-alert message="Warning" type="warning" show-icon>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert message="Error" type="error" show-icon>
|
</a-alert>
|
||||||
<template #icon><smile-outlined /></template>
|
<a-alert message="Error" type="error" show-icon>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert
|
</a-alert>
|
||||||
message="Success Tips"
|
<a-alert
|
||||||
description="Detailed description and advices about successful copywriting."
|
message="Success Tips"
|
||||||
type="success"
|
description="Detailed description and advices about successful copywriting."
|
||||||
show-icon
|
type="success"
|
||||||
>
|
show-icon
|
||||||
<template #icon><smile-outlined /></template>
|
>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert
|
</a-alert>
|
||||||
message="Informational Notes"
|
<a-alert
|
||||||
description="Additional description and informations about copywriting."
|
message="Informational Notes"
|
||||||
type="info"
|
description="Additional description and informations about copywriting."
|
||||||
show-icon
|
type="info"
|
||||||
>
|
show-icon
|
||||||
<template #icon><smile-outlined /></template>
|
>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert
|
</a-alert>
|
||||||
message="Warning"
|
<a-alert
|
||||||
description="This is a warning notice about copywriting."
|
message="Warning"
|
||||||
type="warning"
|
description="This is a warning notice about copywriting."
|
||||||
show-icon
|
type="warning"
|
||||||
>
|
show-icon
|
||||||
<template #icon><smile-outlined /></template>
|
>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
<a-alert
|
</a-alert>
|
||||||
message="Error"
|
<a-alert
|
||||||
description="This is an error message about copywriting."
|
message="Error"
|
||||||
type="error"
|
description="This is an error message about copywriting."
|
||||||
show-icon
|
type="error"
|
||||||
>
|
show-icon
|
||||||
<template #icon><smile-outlined /></template>
|
>
|
||||||
</a-alert>
|
<template #icon><smile-outlined /></template>
|
||||||
|
</a-alert>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { SmileOutlined } from '@ant-design/icons-vue';
|
import { SmileOutlined } from '@ant-design/icons-vue';
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
export default defineComponent({
|
|
||||||
components: {
|
|
||||||
SmileOutlined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,28 +17,30 @@ Additional description for alert message.
|
||||||
</docs>
|
</docs>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<a-alert message="Success Text" type="success">
|
<a-space direction="vertical" style="width: 100%">
|
||||||
<template #description>
|
<a-alert message="Success Text" type="success">
|
||||||
<p>
|
<template #description>
|
||||||
Success Description
|
<p>
|
||||||
<span style="color: red">Success</span>
|
Success Description
|
||||||
Description Success Description
|
<span style="color: red">Success</span>
|
||||||
</p>
|
Description Success Description
|
||||||
</template>
|
</p>
|
||||||
</a-alert>
|
</template>
|
||||||
<a-alert
|
</a-alert>
|
||||||
message="Info Text"
|
<a-alert
|
||||||
description="Info Description Info Description Info Description Info Description"
|
message="Info Text"
|
||||||
type="info"
|
description="Info Description Info Description Info Description Info Description"
|
||||||
/>
|
type="info"
|
||||||
<a-alert
|
/>
|
||||||
message="Warning Text"
|
<a-alert
|
||||||
description="Warning Description Warning Description Warning Description Warning Description"
|
message="Warning Text"
|
||||||
type="warning"
|
description="Warning Description Warning Description Warning Description Warning Description"
|
||||||
/>
|
type="warning"
|
||||||
<a-alert
|
/>
|
||||||
message="Error Text"
|
<a-alert
|
||||||
description="Error Description Error Description Error Description Error Description"
|
message="Error Text"
|
||||||
type="error"
|
description="Error Description Error Description Error Description Error Description"
|
||||||
/>
|
type="error"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue