Skip to content
New issue

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

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

Already on GitHub? # to your account

Allow stylesheets to explicitly define their public exports #1489

Open
tomrav opened this issue Nov 10, 2020 · 2 comments
Open

Allow stylesheets to explicitly define their public exports #1489

tomrav opened this issue Nov 10, 2020 · 2 comments
Assignees
Labels
core Processing and transforming logic feature New syntax feature or behavior

Comments

@tomrav
Copy link
Collaborator

tomrav commented Nov 10, 2020

Stylable allows multiple types of symbols to be imported across stylesheets:

  • Element - Button
  • Class/Part - .part
  • Stylable variables (build time) - :vars { myVar: green; }
  • CSS variables - --myVar
  • Keyframes - @keyframes blink {}

All of these parts are automatically exposed as a public interface for every stylesheet.

This means that a user that wishes to limit the scope of their exposed style API cannot do so.

Furthermore, once we implement the feature suggested in issue #1484 it becomes even easier for anyone consuming a project to access any part of any stylesheet "legitimately".

Suggested feature - add @st-exports to explicitly manage exports

We can introduce a new feature to Stylable that would allow a user to specify which parts of every stylesheet they wish to expose for external use. Any symbol not mentioned will count as a private member and will not be exposed for import across stylesheets.

If no @st-export definition exists in the stylesheet, the current behavior of everything being public is maintained.

Note: the chosen syntax (@) is in line with our suggested @st-import shorthand suggested in PR #936

Example

A component stylesheet exposing some of its internals

/* button.st.css */
:vars {
    c1: green;
    c2: gold;
}


.icon { --c3: purple; }
.text {}
.private {} /* not included in the export below, hence private */

@keyframes blink {}

@st-export 
    c1 as c11, /* rename exports */
    c2, 
    --c3, 
    icon, 
    text, 
    keyframes(blink);

An index file exposing the desired parts of its API. This in conjunction with the feature in #1484 cover both ends of the import/export relationship.

/* index.st.css */
:import {
    -st-from: "./button.st.css";
    -st-default: Button;
}

@st-export Button; 

A user consuming the 3rd-party exports either through a default import or a `named one.

/* user-code.st.css */
:import {
    -st-from: "3rd-party/index.st.css";
    -st-default: Index(
        Button(
            c11, 
            c2
        )
    );
    -st-named: Button as BtnX(
        c11, 
        c2, 
        --c3, 
        icon, 
        text, 
        keyframes(blink)
    );
}

Possible variation

We can consider using the same sort of destructuring syntax introduced in #1484 in the @st-exports directive as well to narrow down the export to specific parts of a stylesheet root.

/* index.st.css */
:import {
    -st-from: "./button.st.css";
    -st-default: Button;
}

@st-export Button(c1 as c11, c2); 

This example exposes three items, Button the component root, and two variables c1 (aliased to c11) and c2. Any imports passing through this export see only those items. This allows managing the entire project exports through a single outward-facing file.

In concept, this is similar to our CLI generated index file, but within the project source code (instead of dist), and more specific about which parts it exposes.

@tomrav tomrav added feature New syntax feature or behavior core Processing and transforming logic labels Nov 10, 2020
@tomrav tomrav changed the title Allow stylesheets to explicitly define their exported internals Allow stylesheets to explicitly define their public exports Nov 10, 2020
@tomrav
Copy link
Collaborator Author

tomrav commented Nov 12, 2020

Random thought. Everything written above talks about managing exports as a way of limiting the public interface.

Does this relate to the issue raised in #294? Should @st-export also limit use through pseudo-element syntax?

/* button.st.css */
.root {}
.icon {}
.text {}
@st-export icon;
/* user-code.st.css */
:import {
  -st-from: './button.st.css';
  -st-default: Button;
  -st-named: icon  /* exists */, 
             text; /* doesn't exist */
}

Button::icon {} /* exists */
Button::text {} /* doesn't exist? */

@idoros
Copy link
Collaborator

idoros commented Nov 12, 2020

@st-export also limit use through pseudo-element syntax?

If this would change the way pseudo elements are exposed then it be in conflict with @custom-selector.

I would prefer a directive to control access to pseudo-elements. Suggested it a while ago: #294

@tomrav tomrav added this to Stylable May 9, 2022
@tomrav tomrav moved this to ❓ Triage Required in Stylable May 9, 2022
@tomrav tomrav self-assigned this May 9, 2022
@tomrav tomrav moved this from ❓ Triage Required to 🎬 Ready for Work in Stylable May 15, 2022
@tomrav tomrav assigned idoros and unassigned tomrav Jul 4, 2022
@idoros idoros removed this from Stylable Jul 11, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
core Processing and transforming logic feature New syntax feature or behavior
Projects
None yet
Development

No branches or pull requests

2 participants