Skip to content

support $$slots #464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/svelte2tsx/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface InstanceScriptProcessResult {
events: ComponentEvents;
uses$$props: boolean;
uses$$restProps: boolean;
uses$$slots: boolean;
getters: Set<string>;
}

Expand Down
27 changes: 27 additions & 0 deletions packages/svelte2tsx/src/svelte2tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function AttributeValueAsJsExpression(htmlx: string, attr: Node): string {
type TemplateProcessResult = {
uses$$props: boolean;
uses$$restProps: boolean;
uses$$slots: boolean;
slots: Map<string, Map<string, string>>;
scriptTag: Node;
moduleScriptTag: Node;
Expand Down Expand Up @@ -91,6 +92,7 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult {

let uses$$props = false;
let uses$$restProps = false;
let uses$$slots = false;

let componentDocumentation = null;

Expand Down Expand Up @@ -224,6 +226,11 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult {
return;
}

if (node.name === '$$slots') {
uses$$slots = true;
return;
}

//handle potential store
if (node.name[0] == '$') {
if (isDeclaration) {
Expand Down Expand Up @@ -383,6 +390,7 @@ function processSvelteTemplate(str: MagicString): TemplateProcessResult {
events: new ComponentEventsFromEventsMap(eventHandler),
uses$$props,
uses$$restProps,
uses$$slots,
componentDocumentation,
};
}
Expand All @@ -408,6 +416,7 @@ function processInstanceScriptContent(
const implicitTopLevelNames = new ImplicitTopLevelNames();
let uses$$props = false;
let uses$$restProps = false;
let uses$$slots = false;

//track if we are in a declaration scope
let isDeclaration = false;
Expand Down Expand Up @@ -607,6 +616,10 @@ function processInstanceScriptContent(
uses$$restProps = true;
return;
}
if (ident.text === '$$slots') {
uses$$slots = true;
return;
}

if (ts.isLabeledStatement(parent) && parent.label == ident) {
return;
Expand Down Expand Up @@ -821,6 +834,7 @@ function processInstanceScriptContent(
events,
uses$$props,
uses$$restProps,
uses$$slots,
getters,
};
}
Expand Down Expand Up @@ -910,6 +924,7 @@ function createRenderFunction({
isTsFile,
uses$$props,
uses$$restProps,
uses$$slots,
}: CreateRenderFunctionPara) {
const htmlx = str.original;
let propsDecl = '';
Expand All @@ -921,6 +936,15 @@ function createRenderFunction({
propsDecl += ' let $$restProps = __sveltets_restPropsType();';
}

if (uses$$slots) {
propsDecl +=
' let $$slots = __sveltets_slotsType({' +
Array.from(slots.keys())
.map((name) => `${name}: ''`)
.join(', ') +
'});';
}

if (scriptTag) {
//I couldn't get magicstring to let me put the script before the <> we prepend during conversion of the template to jsx, so we just close it instead
const scriptTagEnd = htmlx.lastIndexOf('>', scriptTag.content.start) + 1;
Expand Down Expand Up @@ -973,6 +997,7 @@ export function svelte2tsx(
scriptTag,
slots,
uses$$props,
uses$$slots,
uses$$restProps,
events,
componentDocumentation,
Expand Down Expand Up @@ -1006,6 +1031,7 @@ export function svelte2tsx(
const res = processInstanceScriptContent(str, scriptTag, events);
uses$$props = uses$$props || res.uses$$props;
uses$$restProps = uses$$restProps || res.uses$$restProps;
uses$$slots = uses$$slots || res.uses$$slots;

({ exportedNames, events, getters } = res);
}
Expand All @@ -1022,6 +1048,7 @@ export function svelte2tsx(
isTsFile: options?.isTsFile,
uses$$props,
uses$$restProps,
uses$$slots,
});

// we need to process the module script after the instance script has moved otherwise we get warnings about moving edited items
Expand Down
2 changes: 2 additions & 0 deletions packages/svelte2tsx/svelte-shims.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type SvelteAnimation<U extends any[]> = (node: Element, move: { from: DOMRect, t

type SvelteAllProps = { [index: string]: any }
type SvelteRestProps = { [index: string]: any }
type SvelteSlots = { [index: string]: any }
type SvelteStore<T> = { subscribe: (run: (value: T) => any, invalidate?: any) => any }


Expand All @@ -103,6 +104,7 @@ declare function __sveltets_ctorOf<T>(type: T): AConstructorTypeOf<T>;
declare function __sveltets_instanceOf<T>(type: AConstructorTypeOf<T>): T;
declare function __sveltets_allPropsType(): SvelteAllProps
declare function __sveltets_restPropsType(): SvelteRestProps
declare function __sveltets_slotsType<Slots, Key extends keyof Slots>(slots: Slots): Record<Key, boolean>;
declare function __sveltets_partial<Props = {}, Events = {}, Slots = {}>(
render: () => {props?: Props, events?: Events, slots?: Slots }
): () => {props?: Partial<Props>, events?: Events, slots?: Slots }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
///<reference types="svelte" />
<></>;function render() { let $$slots = __sveltets_slotsType({foo: '', default: ''});

let name = $$slots['name'];
;
() => (<>

<h1>{name}</h1>
<slot name="foo" />
<slot /></>);
return { props: {}, slots: {foo: {}, default: {}}, getters: {}, events: {} }}

export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial(__sveltets_with_any_event(render))) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
let name = $$slots['name'];
</script>

<h1>{name}</h1>
<slot name="foo" />
<slot />
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
///<reference types="svelte" />
<></>;function render() { let $$slots = __sveltets_slotsType({foo: '', default: ''});
<><h1>{$$slots['name']}</h1>

<slot name="foo" />
<slot /></>
return { props: {}, slots: {foo: {}, default: {}}, getters: {}, events: {} }}

export default class Input__SvelteComponent_ extends createSvelte2TsxComponent(__sveltets_partial(__sveltets_with_any_event(render))) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>{$$slots['name']}</h1>

<slot name="foo" />
<slot />