fomantic / Fomantic-UI

Fomantic-UI is the official community fork of Semantic-UI
https://fomantic-ui.com
MIT License
3.55k stars 331 forks source link

Add "export"s to index.d.ts #3070

Closed kutoman closed 2 months ago

kutoman commented 3 months ago

Feature Request

In the case of my project, in order to make use of the types from the fomantic-ui package the types from index.d.ts must be exported. I couldn't manage to get the types imported properly otherwise.

Example (if possible)

export interface JQuery {
    accordion:  FomanticUI.Accordion;
    api:        FomanticUI.API;
    ...
}

export interface JQueryStatic {
    api:        FomanticUI.API;
    flyout:     FomanticUI.Flyout;
    ...
}
lubber-de commented 2 months ago

@KiddoV @prudho As I believe you are intensively using the types: Can you please try and test if simply adding the exports to the interfaces inside index.d.ts will break any of your current usages?

KiddoV commented 2 months ago

@kutoman my project is using types of FUI package without the need to export those interfaces.

Simply import like this to your main.ts file or central ts file of your project (assumed you got FUI from NPM):

import 'fomantic-ui'; //To use FUI types globally

For your reference, my project structure looks like:

app-folder
    └───frontend
                  └───dist
                  └───node_modules
                  └───src
                            └───components
                   |  app.svelte
               |  main.ts    <= Right here!
    └───...
               | ...
kutoman commented 2 months ago

@KiddoV thx. That at least makes it possible to access the types via FomanticUInamespace. But I'm currently working on a library based on Fomantic UI, and your approach forces me to produce redundant code.

Just an example, to explain what I mean: If the interfaces were exported, I could easily do this:

import type { JQuery as FJQuery, JQueryStatic as FJQueryStatic } from "fomantic-ui";

export type ModuleType = keyof FJQuery;
export type StaticModuleType = keyof FJQueryStatic;

but currently, I am forced to repeat and write down the interfaces from the fomantic ui index.d.ts in order to collect all module types as keys. I need those keys due to my abstraction level of my API.

kutoman commented 2 months ago

the bigger issue is, when I do import 'fomantic-ui'; semantic.js from dist gets also automatically loaded. But my library requires an efficient approach, where only the min.js files are loaded via

const moduleLoader = async (type: ModuleType) => import(`../../../semantic/dist/components/${type}.min.js`);

and this works like a charm when I only import the types via import type { JQuery as FJQuery, JQueryStatic as FJQueryStatic } from "fomantic-ui"; (but with the exports ofc)

KiddoV commented 2 months ago

@kutoman thanks for the explanation,

FomanticUI heavily relies on jQuery, and its type definitions are designed ONLY to offer a smooth experience when working with TypeScript applications. The primary reason for not exporting the FUI interfaces is to leverage FUI through the global JQuery and JQueryStatic objects. If we export those interfaces, things will still work, but can lead to issues in code editors like VSCode, which may not recognize the properties on type JQuery<HTMLElement>, resulting in errors such as "Property '' does not exist on type 'JQuery'".

For example, if the interfaces were exported, you might encounter issues like:

// Property 'toast' does not exist on type 'JQuery<Document>'.ts(2339)
$(document).toast({
  //...
});

// Property 'transition' does not exist on type 'JQuery<HTMLElement>'.ts(2339)
$(".main-msgbox").transition("shake", "200ms");

This problem arises because the exported interfaces disrupt the global nature of jQuery plugins. Remember, FUI is not a TypeScript-based ES6 module library; it relies on jQuery's global scope. (FomanticUI v3 will be different 🙂 )

If you want to create a library based on FUI, take a look at other libraries like svantic to see how they wrap FUI without the need to export those interfaces.

kutoman commented 2 months ago

@KiddoV ok I see, thanks for the detailed explanation!

Such a coincidence , I am also working on a library for Svelte and therefore I've already checked Svantic. That's why I wanted to solve this in a more abstract way. I'll publish the repo on github, as soon as it has matured sufficiently. Svantic references all module keys hardcoded. I think I'll do it similarly now. It's not a big deal anyways as the FUI jQuery api is straightforward.

KiddoV commented 2 months ago

@kutoman, we would love to see your library go live, and it's great to see FUI grow along with other libraries based on it.

Please do not hesitate to drop a link to your library here!

kutoman commented 2 months ago

@KiddoV yeah definetely, I will!

just for those, who might be looking for a workaround here:

import the FUI namespace this way:

import type {} from "fomantic-ui";

this way the bundle semantic.js won't get loaded and you still can load the minified chunks of the modules individually.